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