auto 和 decltype
#C++11新特性
2024-08-16
auto
使用了 auto 关键字以后,编译器会在编译期间自动推导出变量的类型,这样我们就不用手动指明变量的数据类型了。auto 仅仅是一个占位符,在编译器期间它会被真正的类型所替代。
注意点
- auto 变量必须在定义时初始化,因为编译器需要根据初始化表达式来推导类型
- auto 不能在函数的参数中使用,因为 auto 后面的变量需要初始化,当时函数的参数还只是声明(哪怕你是给这个函数参数填上默认参数也不行)
- auto 其实在 C++11 不能用于推断函数的返回值,当时 C++14 支持了。在 C++11 不支持推断函数的返回值的情况下,利用 decltype 能解决这个问题
- 当 auto 用于数组或函数指针时,数组会退化为指针类型,函数会退化为函数指针类型
- 推导规则遵循 C++ 类型规则,如:如果表达式是按值传递的,那么 auto 推导出的类型是值类型,而不是引用类型
- 当 = 右边的表达式是一个引用类型时,auto 会把引用抛弃,直接推导出它的原始类型
- auto 关键字不能定义数组
- auto 只能用于类的静态成员,不能用于类的非静态成员(普通成员)
- 一旦类型被推导出来,变量的类型就固定了,不会因为初始化表达式的类型发生变化而改变
最后一点可能不容易理解,举例说明:
1 |
|
在这个例子中,x 的类型被推导为 int,因为 42 是一个整数字面值(int 类型)。即使你在以后改变 x 的值为不同类型的数据,x 的类型也不会改变,它仍然是 int。
1 |
|
在这里,x 已经被推导为 int 类型,因此赋值时,3.14 会被截断为整数 3,因为 x 是 int 类型。
auto 与 const 结合
- 当类型不为引用时,auto 的推导结果将不保留表达式的 const 属性
- 当类型为引用时,auto 的推导结果将保留表达式的 const 属性
decltype
decltype 和 auto 功能相同,但 auto 有些无法做到的 decltype 可以完成。
1 |
|
auto 会根据 value 推断类型,当时decltype 根据 exp 表达式(变量、字面量、带有运算符的表达式)推导出变量的类型,跟 = 右边的 value 没有关系。
当程序员使用 decltype(exp) 获取类型时,编译器将根据以下三条规则得出结果:
- 如果 exp 是一个不被括号( )包围的表达式,或者是一个类成员访问表达式,或者是一个单独的变量,那么decltype(exp) 的类型就和 exp 一致,这是最普遍最常见的情况
- 如果 exp 是函数调用,那么 decltype(exp) 的类型就和函数返回值的类型一致
- 如果 exp 是一个左值,或者被括号( )包围,那么 decltype(exp) 的类型就是 exp 的引用;假设 exp 的类型为 T,那么 decltype(exp) 的类型就是 T&
auto和decltype的区别
类型推导的时机和方式
auto:
- auto 在变量声明和初始化时,根据初始化表达式推导变量的类型。
- auto 只能用于变量声明,并且必须在声明时进行初始化。
- 如果表达式是一个引用或 const,auto 会去掉引用性和 const 修饰符(除非明确指定 auto& 或 const auto&)。
1 |
|
decltype:
- decltype 在编译时根据表达式的形式推导类型,表达式本身并不一定需要被执行。
- decltype 不要求表达式初始化,并且可以用于任何有效的表达式。
- decltype 会保留表达式的原始类型,包括引用性和 const 修饰符。
1 |
|
用途
auto:
- 用于推导变量的类型,简化代码。
- 经常用于遍历容器、返回值复杂的函数调用、lambda 表达式等。
1 |
|
decltype:
- 用于获取表达式的类型,而不是直接声明变量。它可以用于推导函数的返回类型,或者声明与另一个变量具有相同类型的新变量。
- decltype 常用于模板编程、函数返回类型推导,以及需要精确获取类型的场合。
1 |
|
类型推到的结果
auto:
- auto 的推导结果通常是值类型,除非显式使用引用或指针。
- 对于引用类型,auto 会去掉引用和 const 修饰符(除非使用 auto& 或 const auto&)。
1 |
|
decltype:
- decltype 会精确获取表达式的类型,包括引用性和 const 性质。
- 可以区分左值引用、右值引用等不同情况。
1 |
|