C++11 auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype。举个例子:
int a = 10;
auto au_a = a;//自动类型推断,au_a为int类型
cout << typeid(au_a).name() << endl;
typeid运算符可以输出变量的类型。程序的运行结果输出了
int
auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。例如上面的代码,编译的时候,就会把a变量转换为int类型。
auto和其他变量类型有明显的区别:
1.auto声明的变量必须要初始化,否则编译器不能判断变量的类型。
2.auto不能被声明为返回值,auto不能作为形参,auto不能被修饰为模板参数
auto的用法
上面举的这个例子很简单,在真正编程的时候也不建议这样来使用auto,直接写出变量的类型更加清晰易懂。下面列举auto关键字的正确用法。
用于代替冗长复杂、变量使用范围专一的变量声明。
想象一下在没有auto的时候,我们操作标准库时经常需要这样:
#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (std::vector<std::string>::iterator i = vs.begin(); i != vs.end(); i++)
{
//...
}
}
这样看代码写代码实在烦得很。有人可能会说为何不直接使用using namespace std,这样代码可以短一点。实际上这不是该建议的方法(C++Primer对此有相关叙述)。使用auto能简化代码:
#include<string>
#include<vector>
int main()
{
std::vector<std::string> vs;
for (auto i = vs.begin(); i != vs.end(); i++)
{
//..
}
}
for循环中的i将在编译时自动推导其类型,而不用我们显式去定义那长长的一串。
decltype
decltype关键字和auto相互对应的,它们经常在一些场所配合使用。decltype可以在编译的时候判断出一个变量或者表达式的类型,例如:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
void func(auto can) {
int a;
}
int main() {
auto num = 1; //num 是int类型
decltype(num) num2 = num; //num2 也是int类型
return 0;
}
这里decltype拿到了num的类型,然后用这个类型定义了num2做了num的一份copy。
注意事项
auto a4 = 10, a5 = 20, a6 = 30;//正确
auto b4 = 10, b5 = 20.0, b6 = 'a';//错误,没有推导为同一类型
使用auto关键字做类型自动推导时,依次施加一下规则:
int a = 10;
int &b = a;
auto c = b;//c的类型为int而非int&(去除引用)
auto &d = b;//此时c的类型才为int&
c = 100;//a =10;
d = 100;//a =100;
const int a1 = 10;
auto b1= a1; //b1的类型为int而非const int(去除const)
const auto c1 = a1;//此时c1的类型为const int
b1 = 100;//合法
c1 = 100;//非法
const int a2 = 10;
auto &b2 = a2;//因为auto带上&,故不去除const,b2类型为const int
b2 = 10; //非法
这是因为如何去掉了const,则b2为a2的非const引用,通过b2可以改变a2的值,则显然是不合理的。
- 初始化表达式为数组时,auto关键字推导类型为指针。
int a3[3] = { 1, 2, 3 };
auto b3 = a3;
cout << typeid(b3).name() << endl;
程序将输出
int *
int a7[3] = { 1, 2, 3 };
auto & b7 = a7;
cout << typeid(b7).name() << endl;
程序输出
int [3]
void func(auto a) //错误
{
//...
}
cout << sizeof(auto) << endl;//错误
cout << typeid(auto).name() << endl;//错误