Linus Torvalds曾經在十多年前嘗試用C++來開發Linux核心,由於種種原因,很快失敗了。自那時起他就不時表達對C++的不滿。劉江blog上的記錄的這個事件只是最近的一次而已。儘管言辭激烈,但其實話糙理不糙。
時至今日,在一般的場合下,C和C++語言的主要用途就是系統級軟體的開發。具體地說,C/C++寫平台、工具和基礎庫,支援高層的語言來完成應用邏輯。 在9月份《程式員》雜誌上刊登的一篇《微軟架構師談程式設計語言發展》的文章裡,Brian Beckman直截了當地說,C++語言主要是用來開發別的語言的。這話片面一點,如果改成 “C++語言主要是用來支援別的語言的”,那就大體沒錯了。
做系統軟體開發的時候,重要的是理解系統的運作方式,那些漂亮的抽象手法和進階特性是次要的。
有一個有趣的現象,不少做系統軟體的老手,在用過一段C++之後,又回到C。因為在這個層次上,C++對於C的優勢就不突出了。那些進階的抽象結構往往是 不必要的,反而是由於抽象層次的提高,使得開發人員要弄清楚“下面實際發生的事情”變得不太容易了。所以很多老手實際上覺得用C語言控制力更強一些,更得心 應手一些。真正的C語言高手,對於語言和編譯器都很熟悉了,基本上在寫C時候就已經知道編譯器最佳化以後產生彙編代碼是個什麼樣子,甚至可以改變C代碼來引 導編譯器產生最佳化的機器碼。而C++的機制很豐富,很多機制是為了滿足高層應用和架構的需求而準備的,在這個層次上發揮不出來,反而把清晰性給犧牲掉 了。很多時候,一個簡單的語句,到底背後會發生什麼,即使是老手也說不清。比如:
std::string s(“Linux Torvalds");
std::string scopy = s;
上面這段代碼不過是建立兩個內容相同的字串副本,但是沒有任何一個人能夠在不瞭解更多資訊的情況下清楚地描述背後所發生的事情,因為不同的STL對於 string的實現方式不同,因此在copy assignment時表現也不同,有的可能是簡單地複製字串對象,有的可能具有ref-counting機制,需要建立對象、設定對象值、增加引用計 數,有的沒有考慮執行緒安全性,有的考慮了執行緒安全性,還得加鎖解鎖,對不起,加解鎖也還有很多做法。建立新的string對象時,有時還需要調用記憶體配置 器,而這個東西的實現又五花八門,有的直接new char[],有的從內建的memory pool申請,memeory pool是不是安全執行緒的?對不起,這次可能又要涉及加解鎖問題。memeory pool會不會已經滿了?要不要次第調用new/malloc申請新的記憶體塊?總之,後面的事情夠多夠複雜,沒有相當功力,對平台瞭解不夠深入,很難說出個子午卯酉來。
一個字串複製尚且如此,別的進階特性就更不用說了。所以很多人寧可麻煩一點,也不願意使用C++,這還是可以理解的。
就我個人來說,我還是願意用C++的,特別是在C裡寫一遍又一遍realloc的時候,就想起 string::operator+=()的好處來了。大概是STL給我的印象太深了,寫演算法程式的時候,不用STL就覺得不爽,一個transform 就可以搞定的事情,非要用for迴圈,這會讓我感覺渾身不自在。所以一般情況下,拿到一個什麼問題,我還是會用C++去解決的。對我來說, Torvalds的話其實是很中肯的,即使是用C++,也要儘可能搞清楚其背後發生的事情,這樣在寫low level程式的時候才會有把握。如果是設計應用層級的程式,就儘可能不用C/C++,把底層的事情都忘掉,專心專意做好應用程式層的設計才是正道。