C++11新特性之新类型与初始化
C++11新特性之新類型與初始化
snoone | 2016-06-23 11:57 ?? 瀏覽量(148) ?? 評論(0) ??推薦(0) 數據這是C++11新特性介紹的第一部分,比較簡單易懂,但是也有一些有趣的地方。
不想看toy code的讀者可以直接拉到文章最后看這部分的總結。
新類型
long long類型
C++11標準中新加入了long long類型屬性,占用空間不小于long類型。測試代碼如下:
| 1 2 3 4 | long?large?=?LONG_MAX; long?long?long_large?=?LLONG_MAX; long?long?long_long_large?=?1LL?<<?63; cout<<"test?long?long:"<<large<<'\t'<<long_large<<'\t'<<long_long_large<<endl; |
在我的機器上實測,long long類型和long類型同樣使用64bit空間。
nullptr字面量
C++11標準中專門為空指針增加了nullptr字面量,同時不推薦再使用NULL或者0表示空指針。
| 1 2 3 4 | int?*p1?=?nullptr; int?*p2?=?0; int?*p3?=?NULL; cout<<"test?nullptr:?"<<(p1?==?p2)<<'\t'<<(p1?==?p3)<<endl; |
最終測試結果,nullptr和NULL和0是一樣的。
constexpr
C++11標準中新增constexpr用于聲明常量表達式,編譯器會驗證此變量的值是否是一個常量表達式。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | int?out_i?=?0;?//?out_i定義于函數外部 ... constexpr?int?mf?=?20; constexpr?int?limit?=?mf?+?1; constexpr?int?*p4?=?&out_i; //?the?following?would?cause?a?make?error? //?since?large?is?not?a?constexpr //constexpr?int?wrong?=?large?+?1;? //?since?&in_j?is?not?a?constexpr; //int?in_j?=?0; //constexpr?int?*p5?=?&in_j; |
值得注意的是,constexpr指針可以指向非常量變量,只要此變量定義于函數之外,因為這樣的變量的指針(地址)是可以在編譯期確定的。
另外,下面的constexpr指針與const指針的含義是完全不同的:
| 1 2 3 | constexpr?int?*p6?=?nullptr;?//?a?const?pointer?point?to?an?int //?p6?=?&out_i;?//?error:?p6?is?a?constexpr const?int?*p7?=?nullptr;?//?a?pointer?point?to?a?const?int |
第一個指針表示一個常量指針,即指針的值是常量;而第二個指針表示一個指向const int的指針,即指針指向的值是常量。
constexpr還可以用于函數,constexpr函數是指能用于常量表達式的函數,它遵循以下幾條約定:
a.返回類型是字面值類型
b.形參類型是字面值類型
c.函數體中必須有且僅有一條return語句
| 1 2 3 4 5 6 | constexpr?int?sz()?{?return?42;?} constexpr?int?new_sz(int?cnt)?{?return?sz()?*?cnt;?} constexpr?int?size?=?sz(); constexpr?int?nsize?=?new_sz(mf); //constexpr?int?wrong_size?=?new_sz(out_i);?//?error:?out_i?is?not?a?constexpr cout<<"test?constexpr:?"<<mf<<'\t'<<limit<<'\t'<<p4<<'\t'<<size<<'\t'<<nsize<<'\t'<<p6<<'\t'<<p7<<endl; |
noexcept
noexcept可以用作異常指示符,用于指示一個函數是否會拋出異常。編譯器并不檢查使用了noexcept的函數是否真的不拋出異常,在運行時,如果一個使用noexcept承諾不拋出異常的函數實際拋出了異常,那么程序會直接終止。
| 1 2 3 4 5 6 | void?no_except()?noexcept { ????throw?1; } //?the?following?call?will?cause?terminate //no_except(); |
noexcept還可以帶參數,noexcept(true)表示不會拋出異常,noexcept(false)表示可能拋出異常。
同時noexcept還可以用作運算符,接受一個函數調用,返回一個bool值表示是否會拋出異常。noexcept運算符并不會對其實參進行求值。
將noexcept運算符,結合帶參數的noexcept指示符,可以得到如下常用法:
| 1 2 | void?no_except2()?noexcept(noexcept(no_except())){} cout<<"test?noexcept:?"<<noexcept(no_except())<<'\t'<<noexcept(no_except2())<<endl; |
這種用法表示no_except2和no_except的異常說明保持一致。
初始化
列表初始化
C++11新標準中為很多類型增加了列表初始化的功能。
可以用列表初始化一個簡單變量。
| 1 2 3 | int?single_int1?=?0; int?single_int2?=?{0}; cout<<"test?list?initialization:\n"<<single_int1<<'\t'<<single_int2<<endl; |
可以用列表初始化一個容器(vector,list,map,set…)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | //?vector/list?list?initialization vector<string>?v1?=?{"ab",?"cd",?"ef"}; list<string>?l2{"gh",?"ij",?"kl"}; //vector<string>?v3("mn",?"op",?"qr");?//?wrong?initialization?format cout<<"test?vector/list?list?initialization:\n"<<v1[1]<<'\t'<<l2.front()<<endl; //?map/set?list?initialization map<string,?string>?m1?= { ????{"a",?"A"}, ????{"b",?"B"}, ????{"c",?"C"} }; m1.insert({"d",?"D"}); set<string>?s1?=?{"a",?"b",?"c"}; cout<<"test?map/set?list?initialization:\n"<<m1["d"]<<'\t'<<*s1.find("b")<<endl; |
可以在使用new動態分配內存時使用列表初始化。
| 1 2 3 | vector<int>?*pv?=?new?vector<int>{0,?1,?2,?3,?4}; int?*pi?=?new?int[5]{0,?1,?2,?3,?4}; cout<<"test?new?alloator?using?list?initialization:\n"<<(*pv)[2]<<'\t'<<pi[2]<<endl; |
可以在傳入參數/函數返回值時使用列表初始化。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | m1.insert({"d",?"D"}); vector<string>?error_msg(int?typ) { ????switch(typ) ????{ ????????case?1: ????????????return?{"type1",?"msg1"}; ????????case?2: ????????????return?{"type2",?"msg2"}; ????????default: ????????????return?{}; ????} } pair<string,?string>?get_pair(int?typ) { ????if(typ?==?1)?return?{"key",?"value"}; ????return?pair<string,?string>("default?key",?"default?value"); } vector<string>?err_msg1?=?error_msg(1); vector<string>?err_msg2?=?error_msg(2); vector<string>?err_msg3?=?error_msg(3); cout<<"test?return?value?list?initialization:\n"<<err_msg1[1]<<'\t'<<err_msg2[1]<<'\t'<<err_msg3.empty()<<endl; pair<string,?string>?p1?=?get_pair(1); pair<string,?string>?p2?=?get_pair(2); cout<<"test?return?pair?list?initialization:\n"<<p1.first<<'\t'<<p2.first<<endl; |
類內成員初始化
C++11標準中允許直接對類內成員進行初始化/列表初始化。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class?InitClass { ????public: ????????void?print_class() ????????{ ????????????cout<<field1<<'\t'<<field2<<'\t'<<field3<<'\t'<<field4<<endl; ????????} ????private: ????????int?field1?=?1; ????????int?field2; ????????double?field3?=?1.0; ????????double?field4; }; class?InitClassMgr { ????public: ????????vector<InitClass>?init_objs?=?{InitClass()}; }; InitClass?test_class; cout<<"test?class?member?initialization:\n"; test_class.print_class(); InitClassMgr?mgr; cout<<"test?class?member?of?class?type?initialization:\n"; mgr.init_objs[0].print_class(); |
總結
·?long long類型。
· nullptr字面量用于表示空指針。
· constexpr用于表示常量表達式。
· noexcept可以用于指示一個函數是否會拋出異常,同時可以用作運算符判定一個函數是否承諾不拋出異常。
· 新增基礎類型、容器類型、new分配內存時的列表初始化。構建臨時變量時也可以直接使用列表初始化。
· 可以直接對類內成員進行初始化/列表初始化。
完整代碼詳見new_type_and_keywords.cpp 和 initialize.cpp。
來源:一根笨茄子的博客
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的C++11新特性之新类型与初始化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小心Redis漏洞让你服务器沦为肉鸡
- 下一篇: 程序员应该知道的七个图形工具