今天在CSDN上看到一篇文章,發現C++0x(或者稱C++11或者C++0B)確實有很多令人興奮的新特性,
搜尋一番,看了Stroustrup的C++11FAQ,頗有感想,因此希望與大家共用一下。想必大家都有自己
的看法,歡迎探討。
1. 新特性展示,您是喜歡還是反感?
以下我想展示幾個目前可用的一些新特性,給不想花時間詳細瞭解的讀者一個直觀感受。
(我使用MINGW GCC 4.6.1,注意加--std=c++0x或者--std=gnu++0x)
在C++98中,我要迴圈一個vector<string>:
1 for(vector<string>::const_iterator itr = aVec.begin(); itr != aVec.end(); ++itr){
2 cout << *itr << endl;
3 }
而在新標準中,這樣就行了:
1 for(auto e : aVec){ cout << e << endl;}
這裡展示了兩個特性,新的auto關鍵字和ranged for。auto在新標準中語義變了,成為了
編譯器自動推導類型的意思。而原來的auto關鍵字幾乎沒有什麼作用,local stack變數就是
預設的,幾乎見不到auto的使用。新標準中,使用原來的語義要產生錯誤的!ranged for也
很好理解,就是學了Java或C#等語言的for迴圈,很方便。甚至可以這樣:
1 for(auto i : {1, 2, 3, 4, 5}) {cout << i << endl;}
所以新的代碼應該見到很多auto了,這並不是動態變數,而是簡化了繁冗的工作,讓編譯器
去做低級重複的事情。下面顯示三種比較現代的C++:
1 map<string, vector<int> > *myMap = new map<string, vector<int> >; // 最舊風格
2 shared_ptr<map<string, vector<int> > > myMap = new map<string, vector<int> >; // 舊風格
4 auto myMap = make_shared<map<string, vector<int>>>(); // 新風格
make_shared是一個庫函數,在VC2010中也能用,是一個非常方便的代替new的函數,直接返回
建立對象的shared_ptr。新標準推薦顯式使用智能指標,徹底杜絕delete。例如表達唯一擁有關係
就用unique_ptr,表達共用關係就用shared_ptr,表達弱引用就用weak_ptr,只有表達非擁有關係,
只是為了track一個對象的,才使用*。而且也不用擔心模板的右角括弧問題了。
還有一個小改動是值得注意的,就是類成員的初始化。大家知道在Java或C#中,變數初始話可以直接
在聲明時進行,而在C++中就必須在初始列表中,但是新標準也進行了改進,於是看以下代碼:
1 class A
2 {
3 static const int a = 3; // Ok in 89
4 static int a = 3; // Error: not const in 89
5 const int a = 3; // Error: not static in 89
6 int a = 3; // Error in 89 but Ok in 0x
7 public:
8 A():a(0){} // Ok in 89 but not necessary in 0x
9 }
C++0x還有一個大的改動及加上了語言層級的lambda函數。及可以在需要使用函數指標或函數對象(所謂functor)
的地方使用如下文法聲明一個匿名函數:
1 [](int a, int b){return a>b;}
這相當於把boost的lambda函數庫整合到語言中了,這樣有幾個好處,首先就是沒有外部依賴,
第二可能會降低模版導致的代碼體積增大或效率問題。總體上來說是個不錯的功能,以後C++的
介面庫就可以用類似的方法寫event handler了。
除了語言方面的一些列改進,標準庫更是增加了不少內容。最顯著的是thread、regex等,都是
對C++能力(跨平台的基礎上)的大幅擴充。具體大家可以查資料,在這裡只是簡單一提。
2. C++0x,一門新語言?
或許您已經查閱了很多C++0x相關的文章,或者您只是看了我上面簡短的介紹,您對
C++的演化抱有什麼態度呢?我在CSDN等地看到的更多是抱怨,很多菜鳥認為過於複雜,
難於學習入門。C++他爸認為C++0x是一門新語言,在某種程度上,還真是。
我對C++也是經驗有限,個人感覺C++的發展喜憂參半。對於把C++當成C with classes
的人來說(大多數上點年紀的C++庫都是如此用C++的),完全用新語言寫的代碼,真的有種陌生
之感。我曾看到過一些大量使用模版的代碼,唯一的感覺就是不必要的複雜性,或者是語言
本身的無能,只能通過各種tricks來實現一些本該語言就能實現的東西。
C++的模式太廣了,如果是底層代碼,其實用C加上幾個類,就可以搞得很好;如果是應用
開發,C++嚴重缺少的一個特性就是垃圾收集,為了提高效率,減少記憶體錯誤,於是基於模版
的智能指標開始出現,就是為了在一個不適合做應用程式層開發的語言上提高易用性,又想
不損失效率,後果就是不必要的複雜性。比如類型操作,大的架構都有反射機制,C++一定
程度上也有,就是要損失效率,所以才有各種操作類型的模版。C++的模版真是物盡其用,
被開發到了一種無以複加的程度,結果呢,使用模版的程式,體積快速膨脹,錯誤資訊基本
不可讀,極大增加了調試難度,同時語言的學習曲線變陡了。
C++的新標準旨在提高語言的易用性,一系列變化,很大程度上就是文法層面的改進,
其實本質的語義改變很少。另一個就是把boost中成熟的庫能加的都加進去(或者整合到語言
裡面),於是現代版的C++就出爐了。所以本質上看,C++0x還不是一個新語言。
3. 從新標準看C++語言定位
C++基於C語言並與其相容的情況,使得對應用開發來說,其代碼過於底層,開發效率
低。而現代流行的編譯型語言,例如C#或Java,隱藏了C++一些底層特徵,而吸收了
其一些高層表達方式,加上強大的類庫支援,使得他們的易用性大大提高。如果利用Qt或者
wxWidgets,C++也可以相對容易地完成一些應用開發,但是最終的程式,並不一定
有很大的效率或體積優勢(有興趣的讀者可以比較一下CodeBlocks和SharpDevelop
兩個IDE的運行時記憶體和速度)。
那麼C++到底怎麼定位呢?C++0x似乎在向著應用開發方面發展,因為其試圖通過
智能指標隱藏C++記憶體管理的麻煩,用模版和類來實現各種進階語義,從而能夠直接
把問題映射為語言結構。標準庫也對Unicode、Threading、Atomic Operation、標準
容器、Regex等提供了完善的支援,我想把boost的FileSystem加進來,再有人
實現一個跨平台的std::ui,那麼C++可真可以和Java或C#坐一起了(或者是自降身份?)
作為一個偏向系統編程的語言,卻把泛型和lambda等進階語義作未來的方向,感覺
C++的定位還真是有點複雜(也有點混亂)。
其實做底層開發,把C++當做一個better C完全值得提倡。做遊戲,用到的特性也就是類
的封裝,簡化C一些繁瑣的操作,因為很多C++特性用起來是會降低效率的。做介面等
應用開發,C++的很多特性,和大公司打造的龐大平台(.Net或Java)相比,不論是最佳化、
語言特性、易用性,還是類庫支援,都是比不上的。有時候我感覺用C++的一個優勢是
不用強迫使用者安裝支援平台,但是現在隨著Window7普及,.Net平台都預設裝在那裡了,
真沒有理由放著這麼大好的資源不用,而用C++去做吃力不討好的事情。Python等動態
語言,隨著硬體的升級,其效率劣勢也逐漸消失,Ubuntu推薦的開發工具竟然是Python+
PyGTK,其開發速度和體驗,也是很好的,因為就像.Net之於Windows,Python現在
基本是所有現代Linux發行版預設安裝的語言了。你可能找不到gcc,但你一定可以用
Python。且Python作為一個語言,在各方面都是具有絕對優勢的。
這麼看來,如果C++不對語言本身進行重大變革(變成一個新語言),又想通過各種方式
來提供進階語義,只能治標不治本,始終不適合所謂的高層開發(相對於底層)。
4. 歡迎還是拒絕?
現在C++11已經是標準了,只不過大多數編譯器還沒有完全實現而已。我們當然沒有選擇的
權利,但是C++還是向下相容的,於是我們可以選擇是否使用新功能。
我還是很喜歡C++的,對於有些簡化編程的改進,真是舉雙手贊成。我甚至以後會一直開啟
--std=c++0x的選項,用上所有能用的新特性。如果這就是C++,我就這樣用C++,但是
如果我寫C,我只會用C的功能,並且編譯成C模組,ABI相容性也是很好的。感覺現在
C++和C有點像雙重人格,亟待分為兩個(真正意義上不同的)語言,然後各自發展。
另外,C++的標準io庫還是謹慎為妙(尤其是用gcc),有時會出現莫名其妙的問題,
還是用C的stdio比較保險。且個人認為printf格式更加易用。
這些改進對於初學者可能不是好事,因為初學者直接學C++的話(就像C++老爸那樣,
直接把C++當新語言教),就會很費解,這些都是什麼亂七八糟的東西。只有學過C,
或者學過C++的C子集,然後才能理解,例如,為什麼這麼多莫名奇妙的指標。因為
C++本質上還是C的系統模型。
C++老手可能會覺得,這些東西沒什麼,只不過是把久以形成的編程習慣固定化了。我甚至
希望,以後C++的指標都預設是智能指標吧,這樣能省多少事啊,但是這就打破了對C的相容性。
所以還是那句話,如果C++的語言本質沒有改變,減少痛苦的改進還是歡迎的,但是這對於
語言本身的發展並沒有太大的意義。如果C++能產生新的語言,有志發展成為不在虛擬機器上的
大而全的開發平台,就是另一回事了。