在最近几个 C++ 版本中,auto 越来越常见。很多人打趣说将来 C++ 里面一定全是 auto。本文介绍 C++ 中 auto(新)关键字的用法。
简介
auto 的作用:
- 对于变量,自动推导其类型
- 【C++14起】对于函数,自动推导返回值
- 【C++17起】对于非类型模板参数,自动推导其类型
有两种用法
【C++11起】auto
基于template type deduction进行推导。
在推导变量类型时,这种推导方式会将每个 auto 出现的地方代换做一个模板参数 U。U 的类型可以从等号左边的 P(下面的const auto&
) 和等号右边的 A(下面的1+2
)
1 | const auto& x = 1 + 2; // P = const U&, A = 1 + 2 |
特别地,对于 copy-list-initialization 的情况,auto 要被代换为 initializer_list<U>
。U 的类型同样可以从 P 和 A 推导出来。
1 | auto l = {13}; // P = std::initializer_list<U>, A = {13}: |
对于 direct-list-initialization 的情况,大括号内只允许有一个元素。
1 | auto x2{1, 2}; // error: not a single element |
在推导返回值类型时,同样用模板参数 U 去替换。这个时候 A 就是 return 后面跟的表达式。如果有多个 return,那么它们推导出来必须是一样的。
1 | auto f() { return 42; } // P = auto, A = 42: |
【C++14起】decltype(auto)
类型是decltype(expr)
,expr 就是用来初始化的表达式。它不走上面的 template type deduction 逻辑。
那么这个到底有啥用呢?举几个例子
1 | int i; |
如果一个函数返回右值引用,则其decltype(auto)
是右值引用,但auto
推导为值。
1 | int&& f(); |
对于大括号的形式
1 | auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> |
此外,decltype(auto)
不能有其他的修饰了。
1 | auto *x7a = &i; // decltype(x7a) is int* |
【C++23】auto 可以被用作显式类型转换。如auto (expr)
和auto {expr}
注意,在 trailing return type 中,auto 会在开头来开始这个声明。但它同样可以作为 placeholder 出现在尾部,虽然我也不知道意义在哪里。
1 | auto (*p)() -> int; // declares p as pointer to function returning int |