auto
(C++)
从其初始化表达式中推导声明的变量的类型。
注意
C++ 标准为此关键字定义了初始和修订的含义。 在 Visual Studio 2010 之前,auto
关键字在自动存储类中声明变量;即,具有局部生存期的变量。 从 Visual Studio 2010 开始,关键字 auto
声明其类型从其声明中的初始化表达式推导出的变量。 /Zc:auto[-]
编译器选项控制 auto
关键字的意义。
语法
auto
declarator initializer;
[](auto
param1, auto
param2) {};
注解
auto
关键字指示编译器使用已声明变量的初始化表达式或 lambda 表达式参数来推导其类型。
在大多情况下,建议使用 auto
关键字(除非确实需要转换),因为此关键字具有以下好处:
可靠性:如果表达式的类型发生更改(包括函数返回类型发生更改的情况),它也能工作。
性能:确保不会进行转换。
可用性:不必担心类型名称拼写困难和拼写有误。
效率:代码会变得更高效。
可能不需要使用 auto
的转换情况:
你需要一个特定类型,任何其他类型都不行。
例如,在表达式模板帮助程序类型
(valarray+valarray)
中。
若要使用 auto
关键字,请使用它而不是类型来声明变量,并指定初始化表达式。 此外,还可通过使用说明符和声明符(如 const
、volatile
)、指针 (*
)、引用 (&
) 以及右值引用 (&&
) 来修改 auto
关键字。 编译器计算初始化表达式,然后使用该信息来推断变量类型。
auto
初始化表达式可以采用多种形式:
- 通用初始化语法,例如
auto a { 42 };
。 - 赋值语法,例如
auto b = 0;
。 - 通用赋值语法,它结合了上述两种形式,例如
auto c = { 3.14159 };
。 - 直接初始化或构造函数样式的语法,例如
auto d( 1.41421f );
。
有关详细信息,请参阅初始值设定项和本文档后面的代码示例。
当 auto
用于在基于范围的 for
语句中声明循环参数时,它使用不同的初始化语法,例如for (auto& i : iterable) do_action(i);
。 有关详细信息,请参阅基于范围的 for
语句 (C++)。
auto
关键字是类型的占位符,但它本身不是类型。 因此,auto
关键字不能用于强制转换或运算符,如 sizeof
和(用于 C++/CLI)typeid
。
有用性
auto
关键字是声明复杂类型变量的简单方法。 例如,可使用 auto
声明一个变量,其中初始化表达式涉及模板、指向函数的指针或指向成员的指针。
也可使用 auto
声明变量并将其初始化为 lambda 表达式。 您不能自行声明变量的类型,因为仅编译器知道 lambda 表达式的类型。 有关详细信息,请参阅 Lambda 表达式示例。
尾部的返回类型
您可将 auto
与 decltype
类型说明符一起使用来帮助编写模板库。 使用 auto
和 decltype
声明其返回类型取决于其模板自变量类型的函数模板。 或者,使用 auto
和 decltype
声明函数模板,该模板包装对其他函数的调用,然后返回任何返回类型的其他函数。 有关详细信息,请参阅 decltype
。
引用和 cv 限定符
使用 auto
会删除引用、const
限定符和 volatile
限定符。 请考虑以下示例:
// cl.exe /analyze /EHsc /W4
#include <iostream>
using namespace std;
int main( )
{
int count = 10;
int& countRef = count;
auto myAuto = countRef;
countRef = 11;
cout << count << " ";
myAuto = 12;
cout << count << endl;
}
在前面的示例中,myAuto 是 int
,而不是引用 int
,因此,如果引用限定符尚未被 auto
删除,则输出为 11 11
而不是 11 12
。
使用括号初始值设定项 (C++14) 的类型推导
下面的代码示例演示如何使用大括号初始化 auto
变量。 请注意 B 和 C 与 A 与 E 之间的差异。
#include <initializer_list>
int main()
{
// std::initializer_list<int>
auto A = { 1, 2 };
// std::initializer_list<int>
auto B = { 3 };
// int
auto C{ 4 };
// C3535: cannot deduce type for 'auto' from initializer list'
auto D = { 5, 6.7 };
// C3518 in a direct-list-initialization context the type for 'auto'
// can only be deduced from a single initializer expression
auto E{ 8, 9 };
return 0;
}
限制和错误消息
下表列出了使用 auto
关键字的限制,及编译器发出的相应诊断错误消息。
错误号 | 说明 |
---|---|
C3530 | auto 关键字不能与任何其他类型说明符组合。 |
C3531 | 使用 auto 关键字声明的符号必须具有初始值设定项。 |
C3532 | 你错误地使用了 auto 关键字来声明类型。 例如,声明了方法返回类型或数组。 |
C3533、C3539 | 不能使用 auto 关键字声明参数或模板自变量。 |
C3535 | 不能使用 auto 关键字声明的方法或模板自变量。 |
C3536 | 符号初始化之前无法使用。 在实践中,这意味着无法使用变量来初始化自身。 |
C3537 | 无法强制转换为使用 auto 关键字声明的类型。 |
C3538 | 使用 auto 关键字声明的声明符列表中的所有符号必须解析为相同的类型。 有关详细信息,请参阅声明和定义。 |
C3540、C3541 | sizeof 和 typeid 运算符不能应用于使用 auto 关键字声明的符号。 |
示例
这些代码片段阐释了可使用 auto
关键字的一些方法。
下面的声明等效。 在第一个语句中,将变量 j
声明为类型 int
。 在第二个语句中,将变量 k
推导为类型 int
,因为初始化表达式 (0) 是整数。
int j = 0; // Variable j is explicitly type int.
auto k = 0; // Variable k is implicitly type int because 0 is an integer.
以下声明等效,但第二个声明比第一个更简单。 使用 auto
关键字的最令人信服的一个原因是简单。
map<int,list<string>>::iterator i = m.begin();
auto i = m.begin();
当 for
和范围 for
循环启动时,下列代码片段将声明变量 iter
和 elem
的类型。
// cl /EHsc /nologo /W4
#include <deque>
using namespace std;
int main()
{
deque<double> dqDoubleData(10, 0.1);
for (auto iter = dqDoubleData.begin(); iter != dqDoubleData.end(); ++iter)
{ /* ... */ }
// prefer range-for loops with the following information in mind
// (this applies to any range-for with auto, not just deque)
for (auto elem : dqDoubleData) // COPIES elements, not much better than the previous examples
{ /* ... */ }
for (auto& elem : dqDoubleData) // observes and/or modifies elements IN-PLACE
{ /* ... */ }
for (const auto& elem : dqDoubleData) // observes elements IN-PLACE
{ /* ... */ }
}
下面的代码片段使用 new
运算符和指针声明来声明指针。
double x = 12.34;
auto *y = new auto(x), **z = new auto(&x);
下一个代码片段在每个声明语句中声明多个符号。 请注意,每个语句中的所有符号将解析为同一类型。
auto x = 1, *y = &x, **z = &y; // Resolves to int.
auto a(2.01), *b (&a); // Resolves to double.
auto c = 'a', *d(&c); // Resolves to char.
auto m = 1, &n = m; // Resolves to int.
此代码片段使用条件运算符 (?:
) 将变量 x
声明为值为 200 的整数:
int v1 = 100, v2 = 200;
auto x = v1 > v2 ? v1 : v2;
下面的代码片段将变量 x
初始化为类型 int
,将变量 y
初始化对类型 const int
的引用,将变量 fp
初始化为指向返回类型 int
的函数的指针。
int f(int x) { return x; }
int main()
{
auto x = f(0);
const auto& y = f(1);
int (*p)(int x);
p = f;
auto fp = p;
//...
}
另请参阅
关键字
/Zc:auto
(推导变量类型)
sizeof
运算符
typeid
operator new
声明和定义
Lambda 表达式的示例
初始值设定项
decltype