在C++11中引入类型推导,类型推导能够给编程带来极大的方便性,特别是面对一些复杂的数据类型,不需要再去一步步的确定具体的类型。关于类型推导主要是两类关键词:auto和decltype,本篇文章就主要介绍各自的用法。
auto
首先对auto有个认识,它是个关键字,而不是数据类型,顶多算一个类型声明的占位符。等到确定具体类型后就会进行替换。而替换这个过程是编译器在编译期完成的。
auto的用法:auto 变量名 = 确定类型的变量; 这样声明以后新声明的变量类型就和之前的保持一致,如果只是希望一致,而不关心具体的,用auto是非常方便的。
但auto的使用也有很多注意事项:
1.auto关键字修饰的变量必须初始化
int b;
auto a = b;
auto a; // 错误,必须进行初始化
auto修饰的变量不能作为函数参数使用,因为函数参数没法初始化
2.auto会抛弃引用,保持原有类型
auto &r1 = 0;
auto r2 = r1; // r1是引用类型,r2会抛弃 r2还是int型
3.不能用于类的非静态成员变量的初始化
class A{
auto a = 1; // ×不能用作非静态成员变量
}
4.不能使用auto关键字定义数组,但可以定义指针
int a[10] = {1,1};
auto b = a; // 正确,用auto定义指针
auto c[10] = a; // 错误,不能定义数组
5.不能使用auto推导出模板参数
vector<int> d;
vector<auto> f = d; // 错误,vector是模板,auto无法推导出模板参数
6.二义性情况下不能使用
auto d=0, f=1.0; // 有二义性(前后变量类型不一致),不能推导
7.auto修饰指针和引用时对const和volatile有特殊情况
在之前的逻辑中,如果auto b = a;变量a是什么类型,b就是什么类型。但在修饰指针和引用,对const和volatile有不同,具体规则是:
当变量不是指针或引用时,结果不会保留const和volatile
当变量是指针或引用时,结果会保留const和volatile
int i = 0;
const auto d = i; // d是const int
auto e = d; // e不保留const,是int
const auto& f = i; // f是const int&
auto &g = f; // auto修饰变量是引用,保留const
上面提到了volatile关键字,在此简单介绍下:
Volatile关键字
volatile原义是异变的提醒编译器它后面所定义的变量随时都有可能改变,因此编译后的程序每次需要存储或读取这个变量的时候,告诉编译器对该变量不做优化,都会直接从变量内存地址中读取数据,从而可以提供对特殊地址的稳定访问。。如果没有volatile关键字,则编译器可能优化读取和存储,可能暂时使用寄存器中的值,如果这个变量由别的程序更新了的话,将出现不一致的现象。(简洁的说就是:volatile关键词影响编译器编译的结果,用volatile声明的变量表示该变量随时可能发生变化,与该变量有关的运算,不要进行编译优化,以免出错
用于:多任务环境下,各任务共享标志 从内存中取保证每个任务数据读取的都是正确的
auto最常见的应用:容器的迭代遍历,像int,double这类简单类型就不使用
for (auto it=xx.begin(); it != xx.end(); it++)
auto还有一个使用上的技巧,可以显式的指定类型:
auto 函数名(函数参数...) -> 显式指定类型;
// 举例 等价于int add(int a, int b);
auto add(int a, int b) -> int;
// 举例 等价于string add(string a, string b);
auto add(string a, string b)-> std::string;
decltype
decltype 是“declare type”的缩写,decltype可以得到变量类型,decltype的推导也是在编译期完成
decltype用法:变量类型1 变量名 = 变量值;decltype(变量名) b; // 将b声明为为变量类型1
decltype也有一些注意事项:
1.decltype只是进行类型推导,不计算值
decltype(10+3.14) c; // 只会类型推导,不会计算值
2.decltype中表达式可以是函数调用,推导的类型是函数返回值,但函数返回值不能是void
int hello();
decltype(hello());
3.表达式是左值,推导的是表达式的引用
int a = 1;
decltype(a); // 结果是int&
4.被推导的变量中被const, volatile修饰时,decltype会全部保留
5. decltype修饰变量在声明时可以不定义,可以用于函数参数
decltype(a) c; √
总的来说auto推导变量类型,decltype推导表达式类型auto可以声明一个变量, decltype可以从一个变量或表达式中得到类型。
当然auto和decltype也可以联合使用,把显式定义推广到模板类型:
template<typename A, typename B>
auto add(A a, B b) -> decltype(a+b) {
return a+b;
}
如果能够灵活使用类型推导将会给我们的编程带来极大便利滴~