auto 关键字(类型推导)
从该关键字的初始化表达式中推导变量的类型。
auto declarator initializer;
备注
auto关键字指示编译器使用一个声明的变量的初始化表达式推导其类型。
我们建议对大多数情况使用关键字 auto ,除非您非常需要转换,因为它提供这些优点:
可靠性:,如果表达式的类型改变了--包括函数的返回类型改变了--它仍工作。
性能: 确保不会出现转换。
可用性测试: 不必担心类型名称拼写困难和排印错误。
高效: 则代码会更高效。
您可能不希望使用 auto的转换大小写:
当需要特定类型,并且不做其他操作。
表达式模板帮助器类型 (例如、(valarray+valarray) 和初始值设定项列表,尽管您很少会选择编写 auto x = { 1 }; };和实际需要获取 int。
若要使用 auto 关键字,请声明一个关键字的变量而不是类型,并指定初始化表达式。 此外,还可以通过使用 const、 volatile、指针(*)、引用 (&) 以及 rvalue 引用 (&&) 等说明符和声明符来修改 auto 关键字。 该编译器将计算初始化表达式然后使用此信息推导变量的类型。
初始化表达式可以是分配 (等号语法),直接初始化 (函数样式语法),new 运算符 表达式,或者初始化表达式可以是在 基于范围的 for 语句 (C++) 语句的 for-range-declaration 参数。 有关详细信息,请参阅本主题后面部分的“服务器代码”一节初始值设定项。
auto关键字是类型的占位符,但是,不是类型。 因此,auto 关键字不能用于转换或运算符(例如 sizeof 和 typeid)。
使用率
auto 关键字是一种声明具有复杂类型变量简单的方法。 例如,在初始化表达式涉及模板、函数的指针或成员的指针时使用 auto 来声明变量。
请使用auto声明变量并将变量初始化为 lambda 表达式。 您自己不能声明变量类型,因为只有编译器知道 lambda 表达式的类型。 有关详细信息,请参阅Lambda 表达式的示例。
尾部的返回类型
请使用auto和decltype类型说明符帮助书写模板库。 使用 auto 和 decltype 声明一个模板函数,该函数的返回类型取决于其模板参数的类型。 或者,使用 auto 和 decltype 可以声明一个包装一个调用到另外一个函数的模板函数,然后返回不论是其他函数的返回类型。 有关详细信息,请参阅decltype 类型说明符。
引用和 cv 限定符
请注意使用 auto 删除引用、常量限定符和变量的限定符。 请看下面的示例:
// 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,因此,输出为,11 11而不用 11 12 作为用例,如果引用未由 auto放置。
限制和错误信息
下表列出了使用 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 初始化为类型 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;
//...
}