C++是我最喜歡的語言,它集自由、博大、復雜、簡約、高效于一身,又能很好地均衡這些特點,使它們和平共處,將“不為用到的任何特性付出一點點代價”的宗旨貫徹到底,其他的任何一種語言的都不具備像C++這樣的內涵,使用C++之時,直有C++在手,江山我有的感覺。C雖然能讓你掌管一切,但用C開發,有如戴著鐐銬在跳舞,無時不刻要小心翼翼地人肉管理一切細節,實在太累了。而用C#、JAVA等其他語言時,雖然養尊處優,但想走不尋常路之時,又處處受限制,很有點寄人籬下的味道,未免不痛快。只有C++,既能下,又能上,進可攻,退可守,想怎么樣就怎么樣,盡情地飛翔。只要你愿意,你就可以在這一片世界里隨心所欲地發揮你的一切聰明才智,創造出種種奇技淫巧,而不會受到一點點約束。問題來了,自由得過頭了,就失去了控制,自由未必是好事。好多人,自由得甚至忘記了他要用C++的根本目的是什么,于是,C++到了他的手里,就變成為自由而自由,為復雜而復雜的利器,不但用它來折磨自己,還用它來迷惑別人,以致于忽視了原本要解決的問題,這樣一來,問題就很嚴重了。好的工具本來就是要用來做點實事的,做不了實事,要拿什么來證明自己呢?
對于C++,沒什么好說的。但C++的教育,就有太多的不滿,要指責之處,也實在太多了,其中最為人詬病,就是很多C++的教材,都鼓勵讀者將注意力集中到C++的細節中,而忘記了如何用C++來簡潔質樸地來表達設計思路。關于這一點,很多達人君子也已經一再嚴厲地批評再批評。我也不想重復他們的論調,只想舉兩個例子。
C++因缺乏GC,而廣受非議。但內存管理,其實不值得議論再議論,只要設計編寫得當,少耍小聰明,代碼中出現new和delete的次數可以很少很少,就算出現,也只會出現于底層代碼中。為了彌補GC的缺席,C++界中發明了種種內存管理的巧妙手法,其中最得力的一種辦法就是智能指針,而出現于標準庫中就是大名鼎鼎的auto_ptr了,甚至有人說,一本C++的教材,只要不介紹auto_ptr,就不屬于合格的教科書。但其實,auto_ptr并不見得那么重要,好比以下的代碼
Int* pa = new int;
……
delete pa;
這代碼確實不好,于是該auto_ptr上場表演,變成
auto_ptr<int*> pa(new int);
delete消失了,何其美妙,但其實,最樸實的代碼,連new都可以不用的,既然沒有new,就不需要auto_ptr了,最簡潔的代碼,非常簡單。
Int a = 0;
一行就好,什么都用不了,很多出現auto_ptr的地方,直接用局部變量就可以了。不能使用局部變量的地方,就屬復雜的內存管理了,在那里分配,在那里釋放,都很有必要細細地斟酌一番,auto_ptr并非什么萬能丹,一有內存分配,就搬出auto_ptr,只怕屬本本主義的作風。即此以觀,什么share_ptr,scope_ptr,也就那么一點點作用而已,無須大書特書。
我承認,BOOST精妙無比,那都是C++程序聰明才智的結晶,但其實,真正搬得上臺面,發揮大作用的玩意,為數并不多,好比Tuple,可以方便地返回函數中的多個結果,例如……(請大家自己動手,或baidu或google),乍聽起來,似乎美妙無比。但其實,沒什么作用,什么時候,我們需要從函數中返回多個值?需要從函數中返回多值時,我會盡量地寫本地代碼,實在必須調用函數了,只好搬出指針或引用,將參數傳遞進去,如果數量太多了,那就動用結構,用結構組織這些返回值,這一切,做起來,并沒什么太大的不便。但是如果動用Tuple返回多個結果,可能方便了那么一點點,卻將導致代碼難以維護,因為Tuple里面的值各表示了什么意思,無法直接從代碼中看得出來,用過Tuple的同學自然知道我要說什么。Tuple的實現非常巧妙,如此費盡心思弄出來的東西,不過是一只漂亮花瓶而已,真讓人扼腕嘆息不已,很多C++的庫,尤其是BOOST,都是這個樣子,看起來很精致,用起來,卻完全不是那么一回事,而且還引入很多不必要復雜性,世人稱心智包袱。
……
用C++做設計,很容易就導致庫設計,如果設計出來的庫有用好用,那也罷了,問題是費了九牛二虎之力,搞出來的東西,半點得不到別人的認可,甚至連自己都無法認可,那就太不應該了。
用C++寫代碼,老老實實地寫代碼,不要忘記了編程的用意,別沉浸于語言中,盡量將代碼寫得直白易懂,少賣弄聰明才智, 慎用C++的一切特性,繼承、虛函數、操作符重載、模板、異常、new delete、……,更加不要用它們創造出什么奇技淫巧,必須用它們的時候,必須要有使用它們的理由。確實存在必須使用它們的理由,還堅決不用,那就是傻瓜和偏執狂了,這不是合格的C++碼農,C++雖然不喜歡胡作非為的搗蛋鬼,但也杜絕一切墨守成規的書呆子。