說明
auto
auto在早期C++中的標識臨時變量,由於使用極少且多餘,在C++11中已被用作類型推導使用。
auto自動類型推斷,用於從初始化表達式中推斷出變量的數據類型,可以簡化我們的編程工作。
使用
map<int, map<int,int> > map;
map<int, map<int,int>>::const_iterator itr1 = map.begin();
const auto itr2 = map.begin();
auto i = 1;
注意項
auto聲明的變量必須初始化,這樣編譯期才能從初始化代碼中推導出返回類型。
使用auto就不能在定義數據類型。
auto是一個推導關鍵詞,並不是一個數據類型,因此不能用於類型轉換或其他一些操作,如sizeof和typeid。
推導不同數據類型必須獨立開了,不能寫在一起,例如:
auto x1 = 5, x2 = 5.0, x3='r'; //錯誤使用
auto不能自動推導成CV-qualifiers(constant & volatile qualifiers),除非被聲明爲引用類型,如下:
const int i = 100;
auto j = i; //錯誤用法
auto &k = i; //正確用法
auto會退化成指向數組的指針,除非被聲明爲引用
int a[9];
auto j = a;
cout<<typeid(j).name()<<endl; // This will print int*
auto& k = a;
cout<<typeid(k).name()<<endl; // This will print int [9]
如果初始化表達式是引用,則去除引用語義
int a = 10;
int &b = a;
auto c = b;//c的類型爲int而非int&(去除引用)
auto &d = b;//d的類型才爲int&
decltype
auto除了自動推導出數據類型還必須使用表達式的值去初始化變量,有時候只需要獲取表達式的返回類型,這時該使用decltype,在推導過程中,編譯器只是分析表達式並獲取它的類型,卻不進行實際的計算表達式的值。
例子:
decltype(f()) sum;//sum的類型就是函數f的返回值類型。
注意項
decltype在處理const和引用的方式與auto有些許不同,如果decltype使用的表達式是一個變量,則decltype返回該變量的類型(包括const和引用在內),如下:
const int ci = 42, &cj = ci;
decltype(ci) x = 0; // x 類型爲const int
auto z = ci; // z 類型爲int
decltype(cj) y = x; // y 類型爲const int&
auto h = cj; // h 類型爲int
declval
decltype 可以推導出表達式的數據類型,但是某些情況下,例如:類的成員函數,如果沒有對象,成員函數無法調用,自然無法推導,而declval就是解決這種情況下的自動推導,在推導過程中,declval不需要構造實例。
使用
template<class T>
typename std::add_rvalue_reference<T>::type declval() noexcept;
#include <utility>
#include <iostream>
class Default {
int foo() const { return 1; }
};
class NonDefault{
NonDefault(const NonDefault&) { }
int foo() const { return 1; }
};
int main()
{
decltype(Default().foo()) n1 = 1; // type of n1 is int
decltype(NonDefault().foo()) n2 = n1; // 錯誤: NonDefault沒有默認的構造函數
decltype(std::declval<NonDefault>().foo()) n2 = n1; // 正確使用
}
auto和decltype配合使用
template<class T, class U>
??? mul(T x, U y){
return x*y;
}
這種情況下問號處最好能使用自動推導,正常使用應該爲:
decltype(x*y)
但是由於x和y都是後面傳入的,因此可以使用以下替代
decltype(*(T*)(0) * *(U*)(0))
template<class T, class U>
decltype(*(T*)(0) * *(U*)(0)) mul(T x, U y){
return x*y;
}
爲了避免使用這種難看的寫法,C++使用auto來佔位,如下寫法就可以:
template<class T, class U>
auto mul(T x, U y) -> decltype(x*y) {
return x*y;
}
template<class T, class U>
auto mul(T x, U y){
return x*y;
}
auto與decltype的區別
auto 關注的是表達式返回值的數據類型,而decltype關注的是表達式本身的數據類型。
auto忽略頂層const,decltype保留頂層const。
對引用操作,auto推斷出原有類型,decltype推斷出引用。
對解引用操作,auto推斷出原有類型,decltype推斷出引用。
auto推斷時會實際執行,decltype不會執行,只做分析。
在使用中過程中和const、引用和指針結合時需要特別注意兩者的區別。