auto 和 decltype

C++11引入了auto和decltype关键字,使用它们可以在编译期就推导出变量或者表达式的类型。

auto

auto 让编译器通过初始值来推算变量的类型。显然,auto 定义的变量必须偶初始值。auto在一行定义多个变量时,各个变量的推导不能产生二义性,否则编译失败。

  1. auto item = val + val2;
  2. auto F() -> std::vector<int> { // c++11
  3. return ...;
  4. }
  5. auto F() { // c++14
  6. return ...;
  7. }
  • auto 不能用作函数参数

  • 在类中 auto 不能用作非静态成员变量

通常会在lambda表达式中使用

  1. auto func = [&] {
  2. cout << "xxx";
  3. }; // 对于func你难道不使用auto吗,反正我是不关心lambda表达式究竟是什么类型。
  • 在不声明为引用或指针时,auto会忽略等号右边的引用类型和cv限定

  • 在声明为引用或者指针时,auto会保留等号右边的引用和cv属性

  1. int i = 0;
  2. auto *a = &i; // a是int*
  3. auto &b = i; // b是int&
  4. auto c = b; // c是int,忽略了引用
  5. const auto d = i; // d是const int
  6. auto e = d; // e是int 忽略了 const
  7. const auto& f = e; // f是const int&
  8. auto &g = f; // g是const int&

decltype

auto 用于推导变量类型,而 decltype 则用于推导表达式类型,这里只用于编译器分析表达式的类型,表达式实际不会进行运算。

  1. int func() { return 0; }
  2. decltype(func()) i; // i为int类型

decltype不会像auto一样忽略引用和cv属性,decltype会保留表达式的引用和cv属性

  1. cont int &i = 1;
  2. int a = 2;
  3. decltype(i) b = 2;// b是const int&,在其他地方引用从来就是所指对象的同义词,只有在decltype处例外
  • exp是表达式,decltype(exp)和exp类型相同

  • exp是函数调用,decltype(exp)和函数返回值类型相同

  • 其它情况,若exp是左值,decltype(exp)是exp类型的左值引用

  1. int a = 0, b = 0;
  2. int *p = &a;
  3. decltype(a + b) c = 0; // c是int,因为(a+b)返回一个右值
  4. decltype(a += b) d = c;// d是int&,因为(a+=b)返回一个左值
  5. decltype(*p) e; // *p 解引用是一个左值, c 是 int& 必须初始化

对编译器来讲 deltype((i)) 对把 (i) 当成一个表达式,所以就会被视为左值,结果自然就是左值引用。不加括号的话得到的就是该变量的类型。

declval

declval 是一个函数而 deltype 是一个运算符,declval 返回一个对应类型的值。

  1. auto i = std::declval<int>();