一、auto是什么
C++11新标准引入了auto类型说明符,用它可以让编译器替我们去分析表达式所属的类型,由于auto会让编译器根据初始值来推演变量的类型,所以auto定义的变量必须有初始值。
二、auto的使用
#include<iostream>
using namespace std;
#include<map>
int main()
{
int a = 0;
auto b = a; // 这里b的类型是根据a的类型推导出是int
int& c = a; // c是a的引用
auto& d = a; // 推导出a的类型是int,所以d也是a的引用
auto e = &a; // e的类型是int*
// 来看变量或对象的类型
cout << typeid(a).name() << endl;
cout << typeid(b).name() << endl;
cout << typeid(c).name() << endl;
cout << typeid(d).name() << endl;
cout << typeid(e).name() << endl;
// auto在实际中的作用如下
std::map<std::string, std::string> dict;
std::map<std::string, std::string>::iterator it1 = dict.begin();
auto it2 = dict.begin();
return 0;
}
不适用auto如it1,使用auto如it2。原本需要写一大长串的类型,这里我们可以用auto来直接推导,简化了许多代码。
auto也能在一个语句中声明多个变量,一条语句只能有一个基本数据类型,所以该语句中所有变量的初始数据类型必须一致。
int main()
{
int i = 0, * p = &i; // 正确示范
auto sz = 0, pi = 3.14; // 错误示范,sz为整型,pi为double类型
return 0;
}
2.1 auto不能推导的场景
1.auto不能作为函数的参数
void TestAuto(auto a)
{
}
2.auto不能直接用来声明数组
void TestAuto()
{
int a[] = { 1,2,3 };
auto b[] = { 4,5,6 }; // auto类型不能出现在顶级数组类型中
}
三、cosnt与auto
编译器推导出来的auto类型有时候会和初始值的类型并不完全一样,编译器会适当的改变结果类型是其更符合初始化规则。
当引用被作为初始值时,真正参与初始化的是引用对象的值,此时编译器以引用对象的类型作为auto的类型:
#include<iostream>
using namespace std;
int main()
{
int i = 0, &r = i; // r类型是int&
auto a = r; // a类型是int
const int ci = i, & cr = ci; // cr类型是const int&
auto b = ci; // 尽管ci类型是const int,但b仍是int类型(ci本身是一个顶层const)
auto c = cr; // 尽管cr类型是const int&,但c仍是int类型
auto d = &i; // d的类型是int*
auto e = &ci; // e的类型是const int*(对常量对象取地址是一种底层const)
// e是指针类型,所以e可以修改ci的值,但ci的类型是const不可修改,所以e是const int*类型
return 0;
}
auto一般会忽略掉顶层const,而保留底层const。
四、推断规则小结
1.对于一般类型(无const无引用),直接根据表达式的类型进行推断。
2.对于含有const的类型,会忽略顶层const属性(一般赋值时),而保留底层const属性(如指针和引用,因为涉及到了修改原对象)。
3.对于被忽略掉的引用类型或const属性,如果想要保留,需要自己额外加上&或const。