- auto被解释为一个自动存储变量的关键字,也就是申明一块临时的变量内存
auto double a=3.7;
C++ 98标准/C++03标准
- 同C语言的意思完全一样:auto被解释为一个自动存储变量的关键字,也就是申明一块临时的变量内存。
C++ 11标准
- 在C++11标准的语法中,auto被定义为自动推断变量的类型。
例如:
auto x=5.2;//这里的x被auto推断为double类型
map<int,int>m;
for(auto it=m.begin();//这里it被auto推断为map<int,int>::iterator类型
it!=m.end();++it)
{
//....
}
auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。是否会造成编译期的时间消耗,
auto使用注意事项:
(1)auto 变量必须在定义时初始化;
(2)定义在一个auto序列的变量必须始终推导成同一类型,如:
auto a = 1, b = 2, c = 3; // 正确
auto a = 1, b = 2.2, c = 'c'; // 错误(这个道理和第一点注意事项相同)
(3)如果初始化表达式是引用,则去除引用语义,如:
int a = 1;
int &b = a;
auto c = b; // 此时c的类型被推导为 int32,而不是int32&
auto &c = b; // 此时c的类型才是int&
(4)如果初始化表达式为const或volatile(或者两者兼有),则除去const/volatile语义。
const int a = 10;
auto b= a; // b的类型为int而非const int(去除const)
const auto c = a; // 此时c的类型为const int
b = 100; // 合法
c = 100; // 错误
(5)如果auto关键字带上&号,则不去除const语义。
const int a = 10;
auto &b = a; // 因为auto带上&,故不去除const,b类型为const int
b = 10; /非法
(6)初始化表达式为数组时,auto关键字推导类型为指针。
int a[3] = { 1, 2, 3 };
auto b = a;
std::cout << typeid(b).name() << std::endl; // 这里输出 int*
(7)如果表达式为数组且auto带上&,则推导类型为数组类型。
int a[3] = { 1, 2, 3 };
auto &b = a;
std::cout << typeid(b).name() << std::endl; // 这里输出 int[3]
(8)函数或模板参数不能被声明为auto。
void func(auto a) // 错误
{
//...
}
(9)auto不是一个真正的类型,仅仅是一个占位符,不能使用一些以类型为操作数的操作符,如sizeof或typeid:
std::cout << sizeof(auto) << std::endl; // 错误
std::cout << typeid(auto).name() << std::endl; // 错误
- 简单的变量声明类型,不建议用auto关键字,而是应更清晰地直接写出其类型。
- auto关键字更适用于类型冗长复杂、变量使用范围专一时,使程序更清晰易读,比如下面
std::vector<int> vect;
for(auto it = vect.begin(); it != vect.end(); ++it)
{ //it的类型是std::vector<int>::iterator
std::cin >> *it;
}
- 或者保存lambda表达式类型的变量声明:
auto ptr = [](double x){return x*x;};//类型为std::function<double(double)>函数对象
- 在模板函数定义时,如果变量的类型依赖于模板参数,使用auto关键字使得在编译期确定这些类型,如:
template <class T, class U>void Multiply(T t, U u)
{
auto v = t * u;
std::cout<<v;
}
- 模板函数的返回类型如果也是依赖于从模板参数推导,
template <typename _Tx, typename _Ty>
auto multiply(_Tx v1, _Ty v2) -> decltype( _Tx * _Ty )
{
return v1*v2;
}
auto result = multiply(101, 1.414); // 结果类型是double
- auto关键字的类型完美转发
C++11使用auto声明变量时,如:auto&& var=initValue;
“auto&&”并不意味着这一定是右值引用类型的变量,而是类似于模板函数参数的类型推导,既可能是左值引用,也可能是右值引用。其目的是把初始化表达式的值分类情况,完美转发给由auto声明的变量。C++11的左值引用与右值引用总结 也即:
1.如果初始化值(initializer)是类型A的左值,则声明的变量类型为左值引用A&;
2.如果初始化值是类型A的右值,则声明的变量类型为右值引用A&&。
#include<iostream>
#include <vector>
#include <typeinfo>
using namespace std;
struct Widget{};
Widget makeWidget(){ return Widget(); } // 类工厂函数
int main()
{
Widget&& var1 = Widget(); // var1的类型是右值引用,但是作为左值
auto&& var2 = var1; //var2的类型是左值引用
std::vector<int> v = { 1, 2, 3 };
auto&& val = v[0]; // std::vector::operator[]的返回值是元素左值,所以val的类型是左值引用
Widget&& var3 = makeWidget(); // var3是左值,但它的类型是右值引用
Widget var4 = static_cast<Widget&&>(var1); // var4是左值,但它的类型是右值引用
std::cout << typeid(var1).name() << std::endl;//struct Widget
std::cout << typeid(var2).name() << std::endl;//struct Widget
std::cout << typeid(val).name() << std::endl;//int
std::cout << typeid(var3).name() << std::endl;//struct Widget
std::cout << typeid(var4).name() << std::endl;//struct Widget
}