新特性 - 類型推導

說明

  • 類似於動態語言,C++11支持自動類型推導。

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;

注意項

  1. auto聲明的變量必須初始化,這樣編譯期才能從初始化代碼中推導出返回類型。
  2. 使用auto就不能在定義數據類型。
  3. auto是一個推導關鍵詞,並不是一個數據類型,因此不能用於類型轉換或其他一些操作,如sizeof和typeid。
  4. 推導不同數據類型必須獨立開了,不能寫在一起,例如:
auto x1 = 5, x2 = 5.0, x3='r'; //錯誤使用
  1. auto不能自動推導成CV-qualifiers(constant & volatile qualifiers),除非被聲明爲引用類型,如下:
const int i = 100;
auto j = i; //錯誤用法
auto &k = i; //正確用法
  1. 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]
  1. 如果初始化表達式是引用,則去除引用語義
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的返回值類型。

注意項

  1. 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配合使用

  • auto 佔位,如下:
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;
}
  • C++14 直接改成:
template<class T, class U>
auto mul(T x, U y){
    return x*y;
}

auto與decltype的區別

  1. auto 關注的是表達式返回值的數據類型,而decltype關注的是表達式本身的數據類型。
  2. auto忽略頂層const,decltype保留頂層const。
  3. 對引用操作,auto推斷出原有類型,decltype推斷出引用。
  4. 對解引用操作,auto推斷出原有類型,decltype推斷出引用。
  5. auto推斷時會實際執行,decltype不會執行,只做分析。
  • 在使用中過程中和const、引用和指針結合時需要特別注意兩者的區別。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章