C++ 中 auto 與 decltype 的用法與區別

最近在惡補 C++ 知識的時候,學習到了一些 C++11 標準的新特性,利用這些新特性,我們能夠更快地提高編程效率,從而實現我們的目標,在此特意記下學習過程中所學習到的一些東西,方便日後的回顧和複習。

auto 關鍵字

在我們日常編程的時候,我們常常需要把表達式的值賦給變量,需要在聲明變量的時候,我們必須清楚的知道變量是屬於什麼類型的。然而往往有些時候,我們做到這一點並非易事。爲了解決這個問題, C++11 新標準就引入了 auto 類型說明符,通過使用 auto 關鍵字,我們就能讓編譯器替我們去分析表達式所屬的類型,和原來那些只對應某種特定的類型說明符(例如 int )不同, auto 能讓編譯器通過初始值來進行類型推演,從而獲得定義變量的類型,這樣一來,我們就可以大大地降低我們在編程中出現變量類型錯誤的概率了。

需要注意的一點⚠️:auto 定義的變量必須有初始值。

舉個例子:

#include <iostream>
#include <typeinfo>
using namespace std;

int main(int argc, const char *argv[])
{
  auto value1 = 1;
  auto value2 = 2.33;
  auto value3 = 'a';
  std::cout << "value1 的類型是 " << typeid(value1).name() << std::endl;
  std::cout << "value2 的類型是 " << typeid(value2).name() << std::endl;
  std::cout << "value3 的類型是 " << typeid(value3).name() << std::endl;
  return 0;
}

運行結果如下:

value1 的類型是 i
value2 的類型是 d
value3 的類型是 c

注: typeid() 操作符可以輸出變量的類型,其庫函數在 頭文件中,如上面👆這個例子所示。

編譯器推斷出來的 auto 類型有時候會跟初始值的類型並不完全一樣,編譯器會適當的改變結果類型,使得其更符合初始化規則。例如我們平常用的浮點數類型 float 和 double ,編譯器似乎會優先選擇 double 類型。

但 auto 需要注意的一點就是,使用 auto 能在一個語句中聲明多個變量,但是一個語句在聲明多個變量的時候,只能有一個基本數據類型,所以該語句中所有變量的初始基本數據類型都必須是一樣的。在這裏一定要區別數據類型和類型修飾符!!

例如:

我們在上面代碼中增加 value4 和 value5:

auto value4 = "QAQ", value5 = &value1;

我們可以看到,在編譯時出現了報錯,原因是因爲 value4 推斷出的類型是字符串型,而 value5 推斷出來的類型是指針類型,一條語句在聲明多個變量的時候,只能有一個基本數據類型,所以會有如下的錯誤出現。

decltype 關鍵字

而 decltype 類型說明符也是 C++11 的標準,它是用於從表達式的類型推斷出要定義的變量的類型。

因爲在有些時候,我們會遇到如下這種情況:

我們希望從表達式中推斷出要定義變量的類型,但卻不想用表達式的值去初始化變量,或者當函數的返回值類型爲某表達式的值的類型,這個時候, auto 顯得就很無力了,所以 C++11 又引入了第二種類型說明符 decltype 。它的作用是選擇並返回操作數的數據類型。在此過程中,編譯器只是分析表達式或函數的返回值的類型並得到它的類型,卻不進行實際的計算表達式的值。

舉個例子:

#include <iostream>
#include <typeinfo>
using namespace std;

std::string func(){
  return "Hello World!";
}

int main(int argc, const char *argv[])
{
  decltype(func()) a;
  int i;
  decltype(i) b;
  std::cout << "a 的類型是 " << typeid(a).name() << std::endl;
  std::cout << "b 的類型是 " << typeid(b).name() << std::endl;
  return 0;
}

輸出結果如下:

a 的類型是 NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE
b 的類型是 i

注:decltype()括號中的表達式並不去執行,而 decltype((variable)) 的結果永遠是引用,而 decltype((variable)) 只有當 variable 本身是一個引用是纔是引用。

auto 關鍵字和 decltype 關鍵字的區別

對於 decltype 所用的表達式來說,如果變量名加上一對括號,則得到的類型與不加上括號的時候可能不同。

如果 decltype 使用的是一個不加括號的變量,那麼得到的結果就是這個變量的類型。但是如果給這個變量加上一個或多層括號,那麼編譯器會把這個變量當作一個表達式看待,變量是一個可以作爲左值的特殊表達式,所以這樣的decltype就會返回引用類型。

如:

int i;
decltype(i) // int類型
decltype((i)) // int& 類型

在這裏我們不探討太多的一些具體的細節,只介紹一些常用的一些用法和注意事項,想了解更多的話參考 C++ Primer Plus 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章