cpp中auto和decltype区别

auto

C++11 中,使用 auto 关键字来进行自动类型推导。语法如下:

1
auto name = value;

其中,name 是变量的名字。value 是变量的初始值。其中 auto 是一个占位符,会在编译期间由编译器推导出来。而且由 auto 推导的变量必须初始化,因为是占位符的原因,不能用作声明。

限制:

  1. auto 不能在函数的参数中使用。

我们在定义函数的时候只是对参数进行了声明,指明了参数的类型,但并没有给它赋值,只有在实际调用函数的时候才会给参数赋值。而 auto 要求必须对变量进行初始化。

  1. auto 不能作用于类的非静态成员变量(即没有 static 关键字修饰的成员变量)中。
  2. auto 关键字不能定义数组,比如下面的例子就是错误的:
1
2
char a[] = "abcdefg";  
auto b[] = a; // a 为数组,所以不能使用 auto
1
error: ‘b’ declared as array of ‘auto’
  1. auto 不能作用于模板参数
1
2
3
4
5
6
7
8
9
template <typename T>
class A {
//TODO:
};

int main(){
A<int> C1;
A<auto> C2 = C1; // 错误
}
1
error: invalid use of ‘auto’

decltype

decltype 是 C++11 新增的一个关键字,它和 auto 的功能一样,都用来在编译时期进行自动类型推导。
auto 和 decltype 关键字都可以自动推导出变量的类型,但它们的用法是有区别的:

1
2
3
auto varname = value;
decltype(exp) varname = value;
decltype(exp) varname;

其中,varname 表示变量名,value 表示赋给变量的值,exp 表示一个表达式。

auto 根据等号右边的初始值 value 推导出变量的类型,而 decltype 根据 exp 表达式推导出变量的类型,跟等号右边的 value 没有关系。

另外,auto 要求变量必须初始化,而 decltype 不要求。auto 是根据变量的初始值来推导出变量类型的,如果不初始化,变量的类型也就无法推导了。此外,我们必须要保证 exp 的结果是有类型的,不能是 void。例如,当 exp 调用一个返回值类型为 void 的函数时,exp 的结果也是 void 类型,此时就会导致编译错误。

1
error: variable or field ‘b’ declared void

注意:

  1. 如果 exp 是一个不被括号包围的表达式,或者是类成员访问表达式,或者是单独的变量,那么 decltype(exp) 的类型就和 exp 一致。
  2. 如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致。
  3. 如果 exp 是一个左值,或者被括号包围,那么 decltype(exp) 的类型就是 exp 的引用。假设 exp 的类型为 T,那么 decltype(exp) 的类型就是 T&。
  4. decltype 如果是函数调用,因为是在编译时确定,和 sizeof 一样,不会调用一次函数。