C++11的新特征簡略匯總引見 (一)。本站提示廣大學習愛好者:(C++11的新特征簡略匯總引見 (一))文章只能為提供參考,不一定能成為您想要的結果。以下是C++11的新特征簡略匯總引見 (一)正文
甚麼是C++11
C++11是已經被叫做C++0x,是對今朝C++說話的擴大和修改,C++11不只包括焦點說話的新性能,並且擴大了C++的尺度法式庫(STL),並入了年夜部門的C++ Technical Report 1(TR1)法式庫(數學的特別函數除外)。
C++11包含年夜量的新特征:包含lambda表達式,類型推導症結字auto、decltype,和模板的年夜量改良。
1. 概述
比來在看C++ Primer5
恰好看到一半,總結一下C++11外面確切加了許多新器械,假如沒有任何懂得,別說本身寫了,看他人寫的代碼估量都邑有些費勁。C++ Primer5
是進修C++11的比擬好的書本。這篇文章僅總結關於C++11中的新器械,老的器械不再贅述。本文的一切代碼僅僅值列出症結代碼,而且一切特征都曾經用編譯器驗證過,我的編譯情況 gcc 5.3.1 g++ 5.3.1 ,聽說 4.7以上的版本曾經支撐年夜部門C++11的特征,VS系列的編譯器對C++11的支撐情形不甚懂得,假如沒有適合的編譯器,可以點擊這裡 C++shell 這是一個在線的C++編譯體系,外面有多個選項可以選擇C++98,C++11,C++14等,可以在這外面驗證C++11的准確性。
2. long long 類型
long long
類型現實上沒有在C++ 98中存在,而以後被C99尺度收錄,其完成在市情上年夜多半編譯器是支撐 long long 的,然則這個類型正式成為C++的尺度類型是在C++11中。尺度請求long long至多是64位也就是8個字節。一個字面常量應用LL後綴表現long long類型,應用ULL後綴表現unsigned long long
類型。
3. 列表初始化
C++11中周全參加了列表初始化的功效,包含對vector,map,值類型,struct等等都可使用列表初始化,還可以在函數中前往一個花括號括起來的列表,而在這之前我們只能對數組停止列表初始化:
//數組列表初始化 int xx[5]={1,2,3,4,5}; int yy[]={6,7,8,9,0}; //值類型停止初始化 int a{10}; int b={10}; int c={10.123}; // 編譯器報錯,g++ 5.3.1當列表初始化用於值類型的時刻,假如有精度喪失,編譯器會報錯。 //列表初始化還可以用構造體 typedef struct Str{ int x; int y; }Str; Str s = {10,20}; //列表初始化類,必需是public成員,假如含有公有成員會掉敗 class Cls{ public: int x; int y; }; Cls c = {10,20}; //vector不只可使用列表初始化,還可使用列表停止賦值,數組不克不及用列表賦值 vector<int>v1={1,2,3,4,5,6,7,8,9}; // 初始化 vector<int>v2; v2={3,4,5,6,7}; //賦值 //map列表初始化 map<string ,int> m = { {"x",1}, {"y",2}, {"z",3} }; //用函數前往初始化列表只展現症結代碼,相干頭文件自行添加 //同理構造體,類,map的前往也能夠應用初始化列表前往 vector<int> getVector() { return {1,2,3,4,5}; } int main() { vector<int> v = getVector(); cout<<v[0]<<v[1]<<v.size()<<endl; return 0 ; }
4. nullptr 空指針
C++11中新參加的字面值表現不指向任何對象的空指針,之前我們經常用一個預界說的宏NULL來表現空指針,現實上NULL的值是0,新尺度推舉應用nullptr而不是NULL
5. constexpr變量
我們在界說常量的時刻普通應用const來界說,一個常量必需在界說的時刻停止初始化,而且以後弗成更改。一個常量必需應用一個常量表達式停止初始化,而且在編譯時代便可以獲得常量的值,然則若何肯定一個表達式就是常量表達式呢,這個平日是由法式員本身肯定的,例如:
const int a =20; //20是一個字面值,固然也是一個常量表達式,所以用20來為a賦值是沒有成績的 //但是上面的代碼也能夠經由過程編譯,g++ 5.3.1 int a = 20 ; const int x = a; int b[x]={0};
為常量x賦值的是一個變量a,如許做應當是不公道的,然則編譯器沒有申報任何毛病,固然這類毛病是不言而喻的,然則在龐雜的體系中若何斷定一個表達式能否是常量表達式是很艱苦的,例如這裡的a我們一眼便可以斷定其其實不是一個常量表達式。為此C++11供給了一個新的症結字constexpr,應用該症結字界說的常量,由編譯器檢討為其賦值的表達式能否是常量表達式,例如下面的代碼改成:
int a = 20 ; constexpr int x = a;
編譯器編譯的時刻就會報錯說a其實不是常量。明顯constexpr症結字將常量表達式的檢討轉交給編譯器處置,而不是法式員本身,所以應用constexpr界說常量要比const平安。
6. constexpr函數
通俗的函數普通是不克不及用來為constexpr常量賦值的,然則C++11許可界說一種constexpr的函數,這類函數在編譯時代便可以盤算出成果,如許的函數是可以用來為constexpr賦值的。界說constexpr函數須要遵照一些商定,函數的前往類型和一切形參的類型都應當是字面值,普通情形下函數體中必需有且只要一條return語句。
constexpr int size() { return 42; } constexpr int si = size();
履行初始化的時刻編譯器將函數的挪用調換成成果值,constexpr函數體中也能夠湧現除return以外的其他語句,然則這些語句在運轉時不該該履行任何操作,例如空語句,using聲明等。constexpr函數許可其前往值並不是是一個字面值,例如:
constexpr int size(int s) { return s*4; } int a = 20; const int b = 30; constexpr int c = 40; constexpr int si = size(a); //error a是一個變量所以函數前往的是一個可變的值 constexpr int si1 = size(20); //ok 函數前往的現實上是一個常量 constexpr int si2 = size(b); //ok constexpr int si3 = size(c); //ok
由上可知constexpr函數其實不必定前往常量,假如運用於函數的參數是一個常量表達式則前往常量,不然前往變量,而該函數挪用究竟是一個常量表達式照樣異常量表達式則由編譯器來斷定。這就是constexpr的利益。
7. using類型別號
類型別號其實早在C說話中就有了,普通情形下我們應用症結字typedef來聲明一個類型的別號,在C++11中增長了另外一種聲明類型別號的辦法就是應用using症結字,using症結字在C++11之前普通用來援用定名空間。
typedef int INT; // 右邊符號代表左邊 using INT2 = int; // 左邊符號代表右邊 INT a = 20; INT2 b = 30;
8. auto類型指導符
我們界說一個變量的時刻起首必需肯定該變量的類型,而許多時刻其實不是我們先須要一個變量然後為該變量賦值適合的數據,而是我們有一個值然則我們卻不曉得該用甚麼類型的變量存儲它,特殊是C++的模版應用的異常普遍,有時刻要界說一個變量,其類型是很龐雜的會帶有模版的類型參數,例如一個最多見的例子:
map<string ,int> m ; map<string,int>::iterator it = m.begin();
下面的例子中我們界說了一個map<string,int>::iterator類型的變量來寄存 m.begin()的值,這個例子絕對來講還不算艱苦然則我在開端應用map容器的時刻也已經被弄暈過,假如map是一個 map<string,double> 類型則須要界說一個 map<string.double>::iterator it 來寄存了。特殊是假如map和vector之間相互嵌套的情形就更輕易弄錯了。界說這類類型變量的另外一個缺陷就是一個類型的名字常常會很長,試想一下法式代碼中通篇都是這類變量聲明,生怕不會有幾小我看著舒暢吧。不外沒緊要C++11為我們界說了一個新的症結字 auto 用來界說變量,而變量的類型由編譯器主動依據賦值的表達式推導出來,不須要我們顯示界說了。由於auto界說的變量的類型由編譯器依據賦值的表達式推導,所以auto界說的變量必需有初始值,不然編譯器沒法肯定該變量的類型。
auto x = 20; // x 是int auto y = 3.14; // y 是double map<string ,int> m ; auto it = m.begin(); //it 是map<string,int>::iterator
如許是否是便利了很多,並且法式看起來加倍簡練了
auto可以在一條語句中聲明多個變量,然則要包管語句中的基本數據類型只要一個,例如:
auto i=10,*p=&i; // OK i是int,p是int* auto a=10,b=3.14; // Error 類型是int照樣double ?
9. decltype類型指導符
有時刻會有如許的需求,我們須要曉得一個表達式的類型,並應用該類型去界說一個變量,例如:
int a = 10; int b = 20; auto c = a + b; // OK a+b的類型是int,此時c的類型是int,而且c的值是 a+b
auto可以處理部門成績,例如我們界說的變量的類型就是表達式 a+b 的類型,然則假如我們僅僅須要界說一個與表達式 a+b 的類型雷同的變量,然則我們又不願望將表達式a+b的值賦值給方才界說的變量,我們願望賦別的一個值或許是僅僅界說變量而不賦值呢。 這就須要用到C++11 供給的另外一個類型解釋符 decltype了。decltype感化於一個表達式,而且前往該表達式的類型,在此進程中編譯器剖析表達式的類型,其實不管帳算表達式的值。例如
int a = 10; int b = 20; decltype(a+b) c = 50; // OK c的類型就是 a+b 的類型int
關於援用類型decltype有一些特殊的處所:
int a = 20 ; int &b = a; decltype(b) c ; // Error c是援用類型必需賦值 decltype(b) d = a; // OK d是援用類型,指向a
可以看到decltype假如感化於一個援用類型,其獲得的照樣一個援用類型。我們曉得一個援用類型在應用的時刻普通會看成其聯系關系的誰人變量的同義詞處置,例如假如應用 cout<<b<<endl; 個中b現實上相當於a,然則decltype感化於援用類型的時刻會保存援用性質。
假如一個表達式是一個解指針援用的操作,decltype獲得的也是一個援用類型:
int a = 20 ; int *p = &a; decltype(*p) c = a; // c的類型是int& c = 50; cout<<a<<endl; // 輸入50
當decltype感化於一個變量的時刻,變量加不加括號是有差別的,例如:
int a = 20; decltype(a) b = 30; //ok b的類型是 int decltype((a)) c = a ; // ok c的類型是int& 其聯系關系變量 a
加上括號以後編譯器會把(a)看成是一個表達式處置,而變量是一種可以作為賦值語句左值的表達式,所以會說明成援用類型。