你以为我说的自动变量类型auto吗?非也,我们知道C语言中其实也有auto关键字,它和早期C++中的auto关键字一样,它修饰局部变量,表示自动存储期,不过由于默认就是这种,因此我们其实常常见不到这样的写法:
auto int a =10;
- 1.
本文要介绍的并不是上面的auto,而是C++11中引入的auto关键字。
效果
看看下面的代码:
#include<iostream>
#include<vector>
int main()
{
std::vector<int> vec{1,2,3,4,5};
for(std::vector<int>::const_iterator it = vec.begin();it != vec.end();++it)
{
std::cout<<*it<<std::endl;
}
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
对于it的类型,你自己能快速写出来吗?我反正是写不出来。
再看auto版本:
#include<iostream>
#include<vector>
int main()
{
std::vector<int> vec{1,2,3,4,5};
for(auto it = vec.begin();it != vec.end();++it)
{
std::cout<<*it<<std::endl;
}
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
是不是简洁了许多?
没错,今天就是介绍自动类型推导关键字auto。
auto的作用
说实在的,程序员有时候就是“懒”,可能连个表达式的类型都不想写,auto就是这样一个关键字,它让编译器替我们去分析表达式的类型。
当然了,分析的前提是auto定义的变量有初值,如果连值都没有,怎么可能知道它是什么类型?
auto用法
(1) 普通类型推导
例如:
auto i = 10;//i为int类型
auto d = 10.2//d 为double类型
auto f = 10.2f//f为float类型
- 1.
- 2.
- 3.
(2) const关键字修饰的类型推导
通常auto会忽略掉顶层const(本身是常量,如int *cosnt p),而会保留底层const(指向的对象是常量,如const int* p)。
举个例子顶层const的例子:
const int ci = 10;
auto aci = ci;//忽略顶层const,推导ci是int,所以aci类型是int
const auto ca = ci//推导ci是int,但是前面有const,所以ca是const int
- 1.
- 2.
- 3.
再说一个底层const的例子:
const int arr[] = {11};
auto p = arr;//arr 是const int *,这是底层const,推导后,保留底层const,所以p是 const int*
- 1.
- 2.
arr数组名被当成指针是,是const int*类型,或者说是int const*,它指向的对象是只读的,因此是底层const,保留,最终p的类型也是int const *。
当然auto还可以设置引用类型,例如:
const int ci = 10;
auto &cp = ci;//cp是一个整型常量引
- 1.
- 2.
如果是字面值,则必须加上const:
const auto &ref = 10;//10是字面值,常量引用才能绑定字面值
- 1.
想一想
想想下面推导的size类型是什么?
std::vector<int> vec;
auto size = vec.size();
- 1.
- 2.
没错,它是std::vector::size_type。
要你写下来你肯定不愿意。
不过下面这样是没法推导的奥:
vector<string> aa;
//vector<string> bb = aa;//无法推导出模板类型
- 1.
- 2.
下面这段程序帮你查看真正类型的名称,仅供参考:
#include <iostream>
#include <vector>
#include <cxxabi.h>
#include <typeinfo>
int main()
{
int status;
char *realname;
auto type = 1.1;
realname = abi::__cxa_demangle(typeid(type).name(), 0, 0, &status);
std::cout << typeid(type).name() << " => " << realname <<std::endl;
free(realname);
return 0;
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
输出结果:
double
- 1.
总结
乍一看,好像挺简单的那么一回事,不过使用auto最好注意类型推导规则,不是很明确的规则不建议以代码可读性为代价而简化代码。
当然了,它也有以下特点:
- 可能使得代码可读性差
- 某些情况auto得到的类型可能不是你想要的
因此一定要合理使用。