C++中auto的推导规则详解
auto可以同指针、引用结合起来使用,还可以带上cv限定符(cv-qualifier,const和volatile 限定符的统称)。
再来看一组例子:
int x= 0;
auto * a = &x; // a -> int*,auto被推导为 int
auto b = &x; // b -> int*,auto被推导为 int*
auto & c = x; // c -> int&,auto被推导为 int
auto d = c; // d -> int ,auto被推导为 int
const auto e = x; // e -> const int
auto f = e; // f -> int
const auto & g = x; // e -> const int&
auto & h = g; // h -> const int&
由上面的例子可以看出:
口a和c的推导结果是很显然的,auto在编译时被替换为int,因此a和c分别被推导为int* 和 int&。
口b的推导结果说明,其实auto不声明为指针,也可以推导出指针类型。
口d的推导结果说明当表达式是一个引用类型时,auto会把引用类型抛弃,直接推导成原始类型 int。
口e的推导结果说明,constauto会在编译时被替换为constint。
口f的推导结果说明,当表达式带有cons实际上volatile也会得到同样的结果)属性时auto会把const属性抛弃掉,推导成non-const类型int。
口g、h的推导说明,当auto和引用(换成指针在这里也将得到同样的结果)结合时auto的推导将保留表达式的const属性。
通过上面的一系列示例,可以得到下面这两条规则:
1)当不声明为指针或引用时,auto的推导结果和初始化表达式抛弃引用和cv限定符后类型一致。
2)当声明为指针或引用时,auto的推导结果将保持初始化表达式的cv属性。
看到这里,对函数模板自动推导规则比较熟悉的读者可能会发现,auto的推导和函数模板参数的自动推导有相似之处。参见【0voice C++】比如上面例子中的 auto,和下面的模板参数自动推导出来的类型是一致的:
template <typename T> void func(T x) {} // T -> auto
template <typename T> void func(T * x) {} // T * -> auto *
template <typename T> void func(T & x) {} // T & -> auto &
template <typename T> void func(const T x) {} // const T -> const auto
template <typename T> void func(const T * x) {} // const T * -> const auto *
template <typename T> void func(const T & x) {} // const T & -> const auto &
注意:auto是不能用于函数参数的。上面的示例代码只是单纯比较函数模板参数推导和auto 推导规则的相似处。
因此,在熟悉 auto 推导规则时,可以借助函数模板的参数自动推导规则来帮助和加强理解。