C++11 引入 auto 和 decltype 兩種編譯期類型推導機制,極大簡化了複雜類型聲明,尤其在模板編程、STL 迭代器、Lambda 表達式等場景中不可或缺。但兩者推導規則存在微妙差異,掌握核心規則能避免常見陷阱。
核心原則:auto 根據初始化表達式推導類型,忽略頂層 const,保留底層 const。
int x = 0; auto a = x, b = 0; // 皆推導為 int
const int *p = 0; auto px = p; // const int* (保留指向 const) int *q = 0; auto qx = q; // int*
auto ax = x, *xp = &ax, **xxp = &xp; // 合法:基本類型均為 int const int ci = x; auto *px = &x, *pci = &ci; // 錯誤:基本類型不一致 (int vs const int)
int f(int); int arr[100]; auto aiar = arr; // int* auto af = f; // int(*)(int) 函數指針
int x = 0; int &m = x; auto am = m; // int (非引用) ++m; // x 變為 1
const auto &m = x; // 合法
核心原則:decltype 根據表達式推導類型,不求值,保留 const、引用、數組/函數原類型。
int x = 0; const int z = 0; decltype(x) dx = 100; // int decltype(0) dy = 200; // int (字面值為右值) decltype(z) dz = 300; // const int ++dz; // 錯誤:const
const int *p = &x; decltype(p) dp = &x; // const int*
decltype(x) *px = &x, &rx = x, m = x; // 合法
int arr[100]; decltype(arr) dar; // int[100] (非指針) decltype(f) df; // int(int) (函數類型)
int x = 0; int *p = &x; decltype(*p) pr = x; // int& (解引用為左值) ++pr; // x 變為 1 decltype(*p + 0) rr; // int (*p+0 為右值)
| 場景 | auto | decltype |
|---|---|---|
| 依據 | 初始化值 | 表達式 |
| 頂層 const | 忽略 | 保留 |
| 數組/函數 | 退化為指針 | 保持原類型 |
| 引用表達式 | 推導為綁定類型 | 推導為引用類型 |
| 求值 | 需要初始化 | 不求值 |
autodecltypeauto x = expr; decltype(x) y; 組合使用可同時獲得值類型與引用類型