c++11引入新的關鍵詞nullptr,用於表示空指針,用於替換之前c提供的NULL(最初NULL是定義在stdlib中的宏定義,通常是0)。
c++提供了使用typedef定義的別名機制,但是有時候很難理解。為了更好的使用別名機制,c++11提供了新的別名定義機制,類似代碼如下:
// alias declarations using VInt = int; // type alias using PInt = int *; // pointer alias using RInt = int &; // reference alias using MyFunc = int (*)(void); // function pointer alias VInt i = 99; PInt pi = &i; RInt ri = i; MyFunc func = nullptr;
c++11擴展了auto的函數,編譯器可按照實際的初始化參數推斷需要的參數類型,並初始化之。其用法類似下面代碼:
// item初始化為val1+val2的結果 auto item = val1 + val2;
需要注意的一點是,auto、const以及引用類型一起使用的時候其語法可能不是簡單的類型推斷,編譯器推斷類型的機制可能與我們能想到的簡單推斷不太一致。也就是說如果需要定義auto引用、auto常量時需要明確指定,否則直接使用auto編譯器會簡單的使用對應的類型,而直接忽略const和引用的限制。相關簡單示例代碼如下:
/* auto specifier */ // a_i is int, a_pi is a pointer to int, a_ri is a reference to int auto a_i = 0, *a_pi = &a_i, &a_ri = a_i; // error like this, for a_f is float while a_d is double //auto a_f = 0.0f, a_d = 0.0;
c++11提供了新的類型推斷關鍵字decltype,主要用於自動推斷表達式類型,但不需要初始化的情況(auto提供了推斷類型+初始化)。
// result is any type that expr has. decltype(expr) result;
與auto自動類型推斷相比,decltype的自動類型推斷很直接,expr是什麼類型,通常decltype返回也是一樣的類型。用法如下:
/*decltype specifier*/ const int ci = 0, &cr = ci, *cp = &ci; decltype(ci) x = 0;// x has type const int decltype(cr) y = x;// y has type const int & decltype(cr) z;// error,z is a reference and must be initialized decltype(cr+0) b;// b has type int decltype(*cp) c;// error, c is a reference and must be initialized int i = 100; decltype(i) d;// d has type int decltype((i)) e;// error ,e is a reference and must be initialized
需要區分兩點,對於有括號的情況、以及指針取值的情況,decltype返回的是左值引用(上面代碼中的後兩個error)。
c++本身的for循環需要三個語句,初始化、條件、增量,對於有些操作需要額外寫很多代碼。針對需要遍歷STL容器中的每個元素的情況,可以考慮使用range for。其具體語法如下:
for(declaration:expression) statement;
比如我們把std::string的字母全部變成小寫字母可以這麼寫:
/* range for */ using std::string; string str("UPPER test"); for (auto &c : str) c = tolower(c);
尤其是配合auto和decltype使用,更可以節省很多代碼(相信大家都有使用STL迭代器的經驗,代碼很長,但功能就是為了遍歷)。
需要注意一點,range for在使用時不能向容器中插入或刪除元素,只能修改。
結合c++11,變量初始化有以下幾種方式:
int x = 0; int x = {0}; // list initialization int x(0); int x{0}; // list initialization
針對STL模板定義也提供了新的形勢,示例代碼如下:
/* vector */ vector<vector<int>> ivec; // list initialization vector<string> strvec{"a", "bc", "def"}; vector<string> v2{"123"}; vector<string> v3{5}; vector<string> v4{5, "s"};
使用大括號的通常是列表初始化,但是某些情況也不是,比如上例中v3、v4實際調用的vector的構造函數(這是編譯器做的處理,在初始化列表中的類型和模板類型不匹配時)。
本文內容主要是關於 c++ primer 第五版的前4章中涉及c++11內容的整理。
所有代碼都在gcc v4.8.1的版本中編譯測試過,相關源碼可以從我的git下載,url如下:https://git.oschina.net/Tocy/SampleCode.git,位於c++11目錄下的cpp_primer_test1.cpp文件中。