一、概念
在C++11引入了auto类型说明符,其作用:编译器替我们去分析表达式所属的类型。auto让编译器根据其初始值来推断变量的类型。
在一些弱类型语言如JavaScript中,用var
定义变量而无需指定特定的数据类型;而在C++则是由编译器根据初值判断变量类型。
auto x = 3.14;
编译根据3.14
推断出x是double
类型。可以使用typeid
检查数据类型:
cout << typeid(x).name() << endl;
输出结果是d
,也就是double
。
二、auto推导的类型
由编译器推导出的auto的类型可能和初始值的类型并不完全一样,比如引用:
(1)引用
int i = 0, &k = i; //i是一个整数,k是i的引用(别名)
auto x = k; //x是一个整数
编译器推导出的x
的类型是int
,虽然k是一个整数的引用,但是编译器会忽略其引用而推导本质。
(2)const
如何顶层和底层,以指针为例。更多关于顶层const:const详解。
- 顶层const:表示指针本身是个常量——常量指针。
- 底层const:指针所指的对象是一个常量——指向常量的指针。
auto一般会忽略掉顶层const,但是底层const则会保留下来。
int i = 1;
const int ci = i;
auto a = ci; //a是一个整数(ci的顶层const特性被忽略掉了)
auto b = &i; //b是一个整型指针(int*)
auto c = &ci; //c是一个指向整型常量的指针(const int *),底层const
三、案例
迭代器iterator访问
看下面的例子,对std::map
容器的iterator访问,书写起来非常复杂,如果嵌套了多层STL容器就更加复杂了。
std::map<std::string, int> myMap;
for (std::map<std::string, int>::iterator it = myMap.begin(); it != myMap.end(); it++)
{
std::cout << it->first << endl;
}
这时候,使用auto
来替代迭代器一堆的代码,就显得很简洁:
std::map<std::string, int> myMap;
for (auto it = myMap.begin(); it != myMap.end(); it++)
{
std::cout << it->first << endl;
}
函数返回值和参数为auto
比如一个模板相加函数Add,使用模板写法如下:
template <typename T>
T add(T x, T y)
{
return x + y;
}
如果模板参数有两种类型呢?返回值可以用auto:
template<typename T, typename V>
auto Add(T t, V v)
{
return t + v;
}
在C++20中,已经可以如下写法:
auto Add(auto x, auto y)
{
return x + y;
}
这样的写法,仅仅用auto
就起到了替代模板的效果。
四、总结
auto作为C++11的新性质,通过让编译器分析表达式所属的类型,简化了程序员对于如迭代器等的操作。若是在项目中广泛使用auto,因为auto都是基于某个参数、某些变量推导而出,那么如果那个参数的变量类型需要修改,auto也会自动随之修改,这样我们就不需要手动修改"auto"指向的类型,方便很多。当然,代价是我们在看代码或者别人看代码的时候,看到一堆auto会显得很难看懂,有利有弊,需要取舍。
参考
- C++ Primer
- C++11特性:auto关键字
- C++auto函数