关于类型推导,在C++中有两个关键字,一个是
auto
还有一个是
decltype
。
对于
auto
大家可能比较熟悉,对于
decltype
不一定熟悉。我也是今天刚学到,所以迫不及待的做个笔记,记录一下。
说明
auto
关键字可以让编译器在编译期间、动态的自动推导出变量的类型。但是使用auto
关键字声明的变量必须立即初始化,否则编译器不知道怎么推导它的类型。decltype
关键字和auto
类似,也是做编译时类型推导。但是decltype
作为一个普通表达式作为参数,返回该表达式的类型,因此无需立即初始化(因为已知表的式的类型)。相比auto
更加灵活。但是使用也稍加繁琐。
两者的区别
auto
关键字不会保留const
、&
等特性,decltype
会保留auto
需要在变量声明的时候就初始化,decltype
不需要在初始化的时候就进行初始化。
写点代码进行说明:
注:要运行下边代码需要安装 boost
库,在ubuntu
下安装的指令是:sudo apt install libboost-dev
,其他平台类似。
#include <iostream>
#include <boost/type_index.hpp>
using namespace std;
int RvalRef()
{
return 10;
}
int main()
{
int i = 10;
int arr[5] = {0};
int *ptr = arr;
int rval = RvalRef();
const int ci = 10;
int &ref = i;
const int &ref2 = ci;
auto var1 = 10;
auto var2 = arr;
auto var3 = ptr;
auto var4 = RvalRef();
auto var5 = i;
auto var6 = ci;
auto var7 = ref;
auto var8 = ref2;
// auto 修饰变量类型,需要立即初始化
// auto test; // error 无法推导 auto类型,需要初始值设定项。
decltype(10) var9;
decltype(i) var10;
decltype(arr) var11;
decltype(ptr) var12;
decltype(RvalRef()) var13;
decltype(ci) var14 = 10;
decltype(ref) var15 = i;
decltype(ref2) var16 = ci;
// 输出var1的类型
cout << "var1.type : " << boost::typeindex::type_id_with_cvr<decltype(var1)>().pretty_name() << endl;
cout << "var2.type : " << boost::typeindex::type_id_with_cvr<decltype(var2)>().pretty_name() << endl;
cout << "var3.type : " << boost::typeindex::type_id_with_cvr<decltype(var3)>().pretty_name() << endl;
cout << "var4.type : " << boost::typeindex::type_id_with_cvr<decltype(var4)>().pretty_name() << endl;
cout << "var5.type : " << boost::typeindex::type_id_with_cvr<decltype(var5)>().pretty_name() << endl;
cout << "var6.type : " << boost::typeindex::type_id_with_cvr<decltype(var6)>().pretty_name() << endl;
cout << "var7.type : " << boost::typeindex::type_id_with_cvr<decltype(var7)>().pretty_name() << endl;
cout << "var8.type : " << boost::typeindex::type_id_with_cvr<decltype(var8)>().pretty_name() << endl;
cout << endl;
cout << "var9.type : " << boost::typeindex::type_id_with_cvr<decltype(var9)>().pretty_name() << endl;
cout << "var10.type : " << boost::typeindex::type_id_with_cvr<decltype(var10)>().pretty_name() << endl;
cout << "var11.type : " << boost::typeindex::type_id_with_cvr<decltype(var11)>().pretty_name() << endl;
cout << "var12.type : " << boost::typeindex::type_id_with_cvr<decltype(var12)>().pretty_name() << endl;
cout << "var13.type : " << boost::typeindex::type_id_with_cvr<decltype(var13)>().pretty_name() << endl;
cout << "var14.type : " << boost::typeindex::type_id_with_cvr<decltype(var14)>().pretty_name() << endl;
cout << "var15.type : " << boost::typeindex::type_id_with_cvr<decltype(var15)>().pretty_name() << endl;
cout << "var16.type : " << boost::typeindex::type_id_with_cvr<decltype(var16)>().pretty_name() << endl;
// decltype 推导表达式类型,并且不需要立即初始化
decltype(var1 / 2.) var17;
cout << "var17.type : " << boost::typeindex::type_id_with_cvr<decltype(var17)>().pretty_name() << endl;
}
输出结果如下:
var1.type : int
var2.type : int*
var3.type : int*
var4.type : int
var5.type : int
var6.type : int
var7.type : int
var8.type : int
var9.type : int
var10.type : int
var11.type : int [5]
var12.type : int*
var13.type : int
var14.type : int const
var15.type : int&
var16.type : int const&
var17.type : double
从结果中可以看出来,auto
的类型推导,不保留 const
、&
属性,但是对于 decltype
的推导,会保留 const
、&
的属性。
因此可知: auto
只推导类型,所以想要对于要声明引用、常量等类型的时候,是需要手动添加const
和 &
关键字的。
总结
两者区别
auto
关键字不会保留const
、&
等特性,decltype
会保留。auto
需要在变量声明的时候就初始化,decltype
不需要在初始化的时候就进行初始化。decltype
需要根据已有表达式、已有变量推导,auto
则不需要。
适用场景
auto
适用于快速推断使用的变量定义、遍历类型推断等场景
decltype
则适用于需要对表达式
类型推导、获取和已有变量完全一致的类型变量等场景
举例
这里举一个适用auto
的例子:使用auto
类型推导,方便很多
#include <vector>
#include <iostream>
using namespace std;
int main()
{
// test();
vector<int> vec = {1, 2, 3};
vector<int> vec2 = {4, 5};
vector<int> vec3 = {6, 7};
vector<vector<int>> vec4 = {vec, vec2, vec3};
// 这里的 & 不能省略,不然会走vector的复制构造,增加开销
for (auto &v : vec4)
{
// 这里同理
for (auto &i : v)
{
cout << i << " ";
}
cout << endl;
}
}
输出结果:
1 2 3
4 5
6 7
写在最后
人无完人,而且对这两个关键字理解也有限,要是有什么不对的地方,欢迎各位指点,我将改正。