C++中的类型推导:auto 和 decltype 介绍


关于类型推导,在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 

写在最后

人无完人,而且对这两个关键字理解也有限,要是有什么不对的地方,欢迎各位指点,我将改正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值