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,其他平台类似。

cpp 复制代码
#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 类型推导,方便很多

cpp 复制代码
#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 

写在最后

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

相关推荐
飞升不如收破烂~3 分钟前
redis的map底层数据结构 分别什么时候使用哈希表(Hash Table)和压缩列表(ZipList)
算法·哈希算法
九圣残炎7 分钟前
【从零开始的LeetCode-算法】3354. 使数组元素等于零
java·算法·leetcode
寒笙LED13 分钟前
C++详细笔记(六)string库
开发语言·c++·笔记
程序猿小柒1 小时前
leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现
java·算法·leetcode
雨中rain1 小时前
贪心算法(1)
算法·贪心算法
不爱学习的YY酱1 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
平头哥在等你2 小时前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
飞滕人生TYF2 小时前
动态规划 详解
算法·动态规划
_OLi_2 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode
ahadee2 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯