C++11特性小結之decltype、類內初始化、列表初始化返回值
作用:返回表示式或變數的型別
返回值規則:
- 若e是一個左值(lvalue,即“可定址值”),則decltype(e)將返回T&
- 若e是一個臨終值(xvalue),則返回值為T&&
- 若e是一個純右值(prvalue),則返回值為T
decltype()不會執行括號內的表示式,decltype返回的型別是用於宣告的,不能用於單純的判斷。比如decltype(a)==int,是不可以的,只能是在定義新的變數、返回值的地方使用:
int a=1; decltype(a) b (等價於int b)
若是給變數加多了1個括號,則會成為一個表示式。
int a = 1; int b=2; decltype((a)) d=b // decltype((a)) 返回型別int&。而引用必須賦初值,所以這裡的d必須賦初值。
若表示式和指標相關的用法:
設p是指向int變數的指標
- decltype(*p)-》返回int& 即引用
- decltype(p)-》返回int* 即指標
- decltype(&p)-》返回int** 即指標的指標。
這裡解釋一下為什麼1返回的是引用而不是int:因為*p返回的本質上就是一個引用,當我們向*p賦值的時候,改變的是變數原本的值,而不是做了一個拷貝,顯然這是引用的性質。
泛型程式設計中使用decltype:
通過和尾置返回型別結合,可以使得返回值可以由編譯器推斷,無需程式設計師指出。主要用於編寫轉發函式
int& foo(int& i); float foo(float& f); template <class T> auto transparent_forwarder(T& t) −> decltype(foo(t)) { return foo(t); }
像這個例子如果沒有decltype,我們無法確定foo(t)到底是兩個備選函式中的哪一個,因為這是在執行時決定的。這樣子我們無法直接編寫transparent_forwarder函式的返回值。
還有其他很多例子,decltype常用於難以確定變數型別的地方,而模板就是為了適配多型別而產生的,所以在泛型程式設計中,很多時候都會用到decltype來做到靈活定義變數型別。
類內初始化
C++11以前是不可以在一個類的資料成員宣告的時候初始化的,除非是一個const的靜態變數:
class A { static int i = 1; //correct,不得不在此賦值,因為const常量必須在宣告時賦值 int num=2; //error,不允許在類內宣告的時候對資料成員初始化 };
這樣子帶來繁瑣的問題就是:儘管我們只是想為所有該類的例項的資料成員都設定一個初始值,也必須自己定義一個建構函式才能做到。
於是在c++11:允許直接在類內初始化值(前提:這個值必須是常量表達式)。
順序:類內部初始化先於建構函式初始化進行,建構函式初始化會覆蓋類內部初始化。也就是說,如果我們即定義了類內初始化值,又定義了自己的建構函式,最終的結果還是按照我們的意願,對資料成員按照建構函式賦值。
使用方法:
class A { int num=2; //correct,C++11允許在類內宣告的時候對資料成員初始化 int a{7} //用花括號賦值也可以,a=7 };
注意:C++11中,仍然沒有改變靜態資料成員必須在類內宣告,類外初始化的事實。
class A { static int d = 1; //error }; int A::d = 1 //correct,一般來說:初始化語句會放在cpp檔案,類定義放在h檔案
列表初始化返回值
在C++11之前,如果我們想要返回一組資料,我們必須在子函式中構造一個對應的容器,藉助容器來進行返回。
vector<int> process() { vector<int> v={1,2,3,4} return v; }
在新標準下,我們可以直接返回字面值,該字面值會用於容器的構造,而無需我們自己去構造。
vector<int> process() { return {1,4}; }
總結
到此這篇關於C++11特性小結之decltype、類內初始化、列表初始化返回值的文章就介紹到這了,更多相關C++11特性decltype、類內初始化、列表初始化返回值內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!