在 C++11及后續版本中,關鍵字auto
和decltype
都是用于類型推導的,但它們的使用場景和行為有所不同。
1.?auto
?關鍵字
作用
auto
?用于自動推導變量的類型,由編譯器根據初始化表達式來確定。
常見用法
// 基本用法
auto x = 42; // int
auto y = 3.14; // double
auto z = "hello"; // const char*// 復雜類型簡化
std::vector<int> vec = {1, 2, 3};
auto it = vec.begin(); // std::vector<int>::iterator// 函數返回值推導(C++14及以后)
auto add(int a, int b) {return a + b; // 返回類型為int
}
注意事項
- 必須初始化:
auto
?變量必須在定義時初始化,否則編譯器無法推導類型。 - 引用和 cv 限定符:
auto
?通常會忽略引用和頂層?const
,除非顯式指定:const int& ref = x; auto a = ref; // a是int(忽略引用和頂層const) auto& b = ref; // b是const int&(保留引用和const)
- 模板類型推導規則:
auto
?使用與模板類型推導相同的規則(T
?推導)。
2.?decltype
?關鍵字
作用
decltype
?用于獲取表達式的類型,而不實際計算表達式的值。
常見用法
int x = 42;
decltype(x) y = 0; // y的類型是int// 復雜類型
std::vector<int> vec;
decltype(vec.size()) size = vec.size(); // std::vector<int>::size_type// 函數返回值類型推導(C++11及以后)
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {return a + b;
}
類型推導規則
- 變量名:
decltype(var)
?返回變量的聲明類型(包括引用和 cv 限定符)。 - 表達式:
decltype((var))
?返回引用類型(因為表達式是左值)。 - 函數調用:
decltype(func())
?返回函數返回值的聲明類型。
int x = 42;
decltype(x) a = x; // a是int
decltype((x)) b = x; // b是int&(因為(x)是左值表達式)
3.?decltype(auto)
(C++14)
作用
decltype(auto)
?用于精確推導類型,保留引用和 cv 限定符,通常用于轉發函數或返回引用的函數。
int& func(int& x) { return x; }auto a = func(x); // a是int(丟失引用)
decltype(auto) b = func(x); // b是int&(保留引用)
4. 對比總結
特性 | auto | decltype |
---|---|---|
推導依據 | 初始化表達式的類型 | 表達式的類型(不計算值) |
引用和 cv 限定符 | 通常忽略頂層 const 和引用 | 保留所有類型信息 |
適用場景 | 變量定義、函數返回值簡化 | 模板元編程、返回類型后置 |
特殊形式 | auto&& (通用引用) | decltype(auto) (精確推導) |
5. 示例
泛型容器遍歷
std::map<std::string, int> dict = {{"apple", 1}, {"banana", 2}};
for (const auto& pair : dict) { // pair是const std::pair<const std::string, int>&// 使用pair.first, pair.second
}
元編程
template<typename T, typename U>
auto max(T a, U b) -> decltype(a > b ? a : b) {return a > b ? a : b;
}
總結
auto
:適合簡化類型名,由初始化表達式推導類型。decltype
:適合精確獲取表達式的類型,常用于模板元編程或保留引用。decltype(auto)
:結合兩者優點,用于精確轉發或返回引用。