文章

C++ 中 auto 和 decltype 的用法 (update 20241106)

1. auto 占位符

1.1 规则

auto推导的原则为:保持原有变量的类型(如cv限定),大致分两种情况:

  • auto: auto含义是创建了一个新的变量:
    • 表达式为T或者T&或者const T&auto推导为T – 即新变量的类型去除cv限定 (如果原有表达式有cv限定);
    • 表达式为T* const或者T*auto推导为T* – 新变量去除cv限定;
    • 表达式为const T*或者const T* constauto推导为const T*,即保持指针指向的内存区域的const属性。
  • auto&: auto&含义是alias,故auto&推导的结果是原有类型的的引用,不能少任何一个限定符,如:
    • const T* const推导为const T* const &
    • const T推导为const T&

auto_deference

1.2 一些应用场景

  1. 范围循环
1
2
3
4
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (const auto& num : numbers) {
    std::cout << num << std::endl; // num 的类型被推导为 const int&
}
  1. lambda 表达式
1
2
3
auto add_func = [](int a, int b) -> int {
    return a + b;
};
  1. 结构化绑定(c++17新特性)
1
2
std::pair<int, double> myPair = std::make_pair(42, 3.14);
auto [first, second] = myPair; // 结构化绑定,first 和 second 的类型被推导为 int 和 double
  1. 返回类型后置
1
2
3
4
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) {
    return t + u;
}

2. decltype

decltype 类型推导规则:

2.1 decltype(entity)

如果 entity 是一个不被括号包围的标识符、类访问表达式,那么decltype(entity)entity 类型一致。

2.2 decltype((expression))

如果expression是一个表达式,计算结果为类型T,那么:

  1. 如果 expressionxvalue(将亡值),那么 decltype 的结果是 T&&
  2. 如果 expressionlvalue,那么 decltype 的结果是 T&
  3. 如果 expressionprvalue(纯右值),那么 decltype 的结果是 T

2.3 说明及示例

注意第一点中强调了 entity 是一个不被括号包围的标识符。因为当一个标识符被括号包围时,它就是一个左值表达式了,对应上面第二大点的第二小点。比如说 int x = 0;x 是一个标识符,所以 decltype(x) 的结果为 int。但是 (x) 就是一个左值表达式,decltype((x)) 的结果就是 int&

3. 参考

本文由作者按照 CC BY 4.0 进行授权