0%

C++11特性:auto和decltype关键字简化声明

C11 提供了两个新的关键字 auto 和 decltype 来实现变量的自动类型推断

类型推断有两种,一种是编译时类型推断,我们在编程的时候常常要把表达式赋给一个确定类型的变量,这就需要在声明变量的时候清楚的知道表达式的类型。然而要做到这一点并非容易,有时根本不知道,或者有的类型名字很长,书写不方便。为了解决这个问题,C11新标准引入了 autodecltype两个关键字,用他们可以让编译器在编译的时候自动分析变量的类型。这两个都是编译时编译器自动推断变量类型;另一种 typeid运算符可以在运行时查询变量的类型,由RTTI机制为每个类型产生一个type_info类型的数据。

auto

作用

auto可以在声明变量时根据变量初始值的类型自动为此变量选择匹配的类型。

用法

1
2
3
4
5
6
7
8
9
10
auto f = 3.14;  //double
auto s("hello"); //const char*
auto z = new auto(9); //int *
auto x1 = 5, x2 = 5.0, x3 = 'r'; //错误,必须是初始化为同一类型
std::vector<int> vect;

for(auto it = vect.begin(); it != vect.end(); ++it)
{ //it的类型是std::vector<int>::iterator
std::cin >> *it;
}

decltype

作用

当希望从表达式的类型推断出要定义的变量类型的类型,但是不想用该表达式的值初始化变量,这就是和 auto 的区别,使用auto 即便可以使用表达式初始化一个变量,但是其初始值一定是表达式执行后的返回结果。但是使用这个关键字定义,就不需要显式的执行表达式(函数),也就不需要用表达式的返回值初始化了。

用法

使用函数/表达式推断

1
2
3
4
5
6
7
8
9
10
11
12
auto f(int i){
return i*i;
}

int main(){
decltype(f(1)) x; // x的类型就是函数f的返回值,这个例子中需要确定给定具体的输入参数,可能是存在函数重载的机制,所以编译器需要确定到底调用的哪个函数 但是编译器并不实际调用 函数 f

int i = 42, *p = &i, &r = i;
decltype(r + 0) b; // 正确,加法的结果是int 因此b是一个未初始化的 int 变量
decltype(*p) c; // 错误,c是int& 必须初始化
decltype((i)) d; // 错误,d是int& 必须初始化
}

其他注意点:

  • 表达式是解引操作,则将得到引用类型,例如例子中的 指针变量
  • 如果里面还有一层括号,那么也是引用类型,需要初始化

使用变量推断

decltype处理 顶层 const 与 引用 的方式与 auto 不同,如果使用的表达式是一个变量,那么返回该变量的类型 (包括顶层const 和 引用在内)

1
2
3
4
const int ci = 0, &cj = ci;
decltype(ci) x;
decltype(cj) y = x;
decltype(cj) z; // 这个写法错误,因为cj是引用类型,定义的z也是引用类型,而引用类型必须有初始值