文章目录
- 1. 定义
- 1.1 注意事项
- 2. 推导规则
- 3. 返回类型推导(C++14)
- 4. lambda表达式中使用auto类型推导
- 5. 非类型模板形参占位符(C++17)
1. 定义
在C++11以前,auto关键字是用来声明自动变量的。从C++11起auto被用来:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。
auto a = 5; // 推断为int
auto b = "Hello"; // 推断为const char*
// 返回类型后置, auto为返回值占位符(主要用于函数模板的返回值推导)
auto fun(int x, int y) -> int
{
return x + y;
}
auto占位符会让编译器去推导变量的类型。若编写的代码让编译器无法推导则会编译失败,例如:
auto a; // 推导失败
a = 5;
编译器报错:
由此可知,在使用auto占位符声明变量时必须初始化变量。
1.1 注意事项
- 当用一个auto关键字声明多个变量时,编译器遵从由左往右的推导规则,以最左边的表达式推断auto类型。
int a = 5;
auto* p = &a, m = 10; // auto被推断为int, 所以m为int
- 当使用条件表达式初始化auto声明的变量时,编译器总是使用表达能力更强的类型。
auto a = true ? 5 : 5.0; // a被推断为double类型
通过反汇编查看可得
- 静态成员变量可以用auto声明并初始化,前提是auto必须用const限定符。
class CusType
{
auto a = 0; // 错误,无法通过编译
static const auto b = 0; // 正确
static inline auto c = 0; // C++17支持 (测试环境VS2019编译失败,linux g++可以)
};
- 在C++20之前,无法在函数形参列表中使用auto声明形参(在C++14中,auto可以为lambda表达式声明形参)。
int fun(auto a) // C++20之前编译失败,C++20编译成功 (测试VS2019编译失败)
{
return a * 10;
}
auto 也可以和new关键字结合
auto p = new auto(5);
2. 推导规则
- 如果auto声明的变量是
按值初始化
,则推导出的类型会忽略cv限定符(即const和volatile)。
const int a = 0;
auto b = a; // auto推导类型为int, b为int
auto& c = a; // auto推导类型为const int, c为const int&
auto* d = &a; // auto推到类型为const int, d为const int*
const auto e = a; // auto推导类型为int, e为const int
- 使用auto声明变量初始化时,目标对象如果是引用,则引用属性会被忽略。
int a = 0;
int& b = a;
auto c = b; // auto推导为int
- 使用auto和万能引用(&&)声明变量时,对于左值会将auto推导为引用类型。
int a = 0;
auto&& b = a; // 推导为int&
auto&& c = 1; // 推导为int
- 使用auto声明变量,如果目标对象是一个数组或函数,则会被推导为对应的指针类型。
int fun(int x)
{
return x * x;
}
int main()
{
int a[8] = {0};
auto b = a; // 推导为int*
auto c = fun; // 推导为int(*)(int)
return 0;
}
- 当auto与列表初始化组合时(C++17),①直接使用列表初始化,列表必须为单元素,auto推导为元素类型;②用等号加列表初始化,列表中可以包含单个或多个元素,auto被推导为
std::initializer_list<T>
,T为元素类型。
①
auto a{ 1 }; // 推导为int
auto b{ 1, 2, 3 }; // 编译失败,不是单个元素
②
auto a = { 1 }; // 推导为std::initializer_list<int>
auto b = { 1, 2.0 };// 编译失败,列表内元素类型不同
auto c = { 1, 8 }; // 推导为std::initializer_list<int>
3. 返回类型推导(C++14)
auto sum(int x, int y) // auto推导为int
{
return x+y;
}
注意:如果有多个return,需保证返回值类型都相同才行。
4. lambda表达式中使用auto类型推导
auto a = [](auto x, auto y) // C++14,lambda形参用auto;
{
return x + y;
};
auto ret = a(14, 23.3); // 返回值推导为double
lambda返回auto引用:
auto fun = [](int& x) ->auto&
{
return x;
};
auto a = 1;
auto& b = fun(a);
assert(&a == &b); // 有相同的内存地址
5. 非类型模板形参占位符(C++17)
template<auto N>
void fun()
{
cout << N << endl;
}
int main()
{
fun<5>(); // N为int类型
fun<'c'>(); // N为char类型
fun<5.2>(); // 编译失败,模板参数不能为double
return 0;
}