auto关键字(类型推导)
从其初始化表达式中推导一个声明的变量的类型。
auto declarator initializer;
备注
auto 关键字指示编译器使用一个声明的变量的初始化表达式中推导其类型。
说明 |
---|
在 Visual C++ 2010之前,auto 关键字是自动存储类说明符。该用法现在是错误。/Zc:auto 编译器选项,这是默认值,指示编译器使用 auto 关键字的新含义。 |
我们建议对大多数情况 auto 使用关键字,除非您非常需要转换,因为它提供这些优点:
可靠性: 更改,则此表达式的类型由函数的返回类型更改有效。
性能: 确保将不会转换。
可用性: 不必担心类型名称拼写困难和排印错误。
性能: 则代码会更高效。
您可能不希望使用 auto的转换大小写:
当需要特定类型,并且不将使。
表达式模板帮助器类型 (例如、(valarray+valarray) 和初始值设定项列表,尽管您很少会选择编写 auto x = { 1 }; };和实际需要获取 int。
若要使用 auto 关键字,请使用它而不是类型来声明变量,并指定初始化表达式。另外,可以修改 auto 关键字通过使用说明符,并声明例如 const,volatile,指针 (*),引用 (&),并且,rvalue 引用 (&&)。该编译器将计算初始化表达式然后使用此信息推导变量的类型。
初始化表达式可以是分配 (等号语法),直接初始化 (函数样式语法),或者 new 运算符 表达式。或初始化表达式可以是在 基于范围的 for 语句 (C++) 语句的 为大小声明 参数。有关更多信息,请参见 初始值设定项 和代码示例文档中。
auto 关键字是类型的占位符,但是,它本身不属于类型。因此,auto 关键字不能用于转换或运算符(例如 sizeof 和 typeid)。
使用率
auto 关键字是一种声明具有复杂类型变量简单的方法。例如,可以使用 auto 声明初始化表达式涉及模板、指向函数的指针或指向成员的指针的变量。
还可以使用 auto 声明和初始化变量传递到 lambda 表达式。因为 lambda 表达式的类型才知道给编译器,不能声明变量的类型。有关更多信息,请参见Lambda表达式的示例。
可以使用 decltype 类型说明符一起使用,auto,帮助编写模板库。使用 auto 和 decltype 声明一个模板函数,该函数的返回类型取决于其模板参数的类型。或者,使用 auto 和 decltype 可以声明一个包装一个调用到另外一个函数的模板函数,然后返回不论是其他函数的返回类型。有关更多信息,请参见decltype类型说明符。
限制和错误信息
下表列出了使用 auto 关键字的限制,和该编译器发出的对应的诊断错误消息。
错误号 |
描述 |
---|---|
auto 关键字不能与其他任何类型说明符一起使用。 |
|
使用 auto 关键字声明的符号必须具有初始值设定项。 |
|
您已误用 auto 关键词来声明类型例如,声明方法返回类型或数组。 |
|
不能使用auto关键字声明参数或模板参数。 |
|
使用 auto 关键字并在 new 表达式内声明的符号必须具有初始值设定项。有关更多信息,请参见operator new (<new>)。 |
|
不能使用auto关键字声明方法或模板参数。 |
|
不能在初始化之前使用的符号。实际上,这意味着变量不能用来对自身进行初始化。 |
|
不能转换至有 auto 关键字声明的类型。 |
|
auto 关键字内声明的声明符列表的所有符号必须解析为同一类型。有关更多信息,请参见声明。 |
|
示例
这些代码段阐释 auto 关键字可以使用的一些用法。
下面的声明等效。在第一个语句中,声明 j 变量为类型 int。在第二个语句,因为初始化表达式 (0) 是整数,所以变量 k 推导为 int 类型。
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 初始化为类型 constint,及将变量 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;
//...
}