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 

写在最后

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

相关推荐
唐诺4 小时前
几种广泛使用的 C++ 编译器
c++·编译器
XH华4 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生4 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_5 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
落魄君子5 小时前
GA-BP分类-遗传算法(Genetic Algorithm)和反向传播算法(Backpropagation)
算法·分类·数据挖掘
冷眼看人间恩怨5 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
菜鸡中的奋斗鸡→挣扎鸡5 小时前
滑动窗口 + 算法复习
数据结构·算法
红龙创客5 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
Lenyiin5 小时前
第146场双周赛:统计符合条件长度为3的子数组数目、统计异或值为给定值的路径数目、判断网格图能否被切割成块、唯一中间众数子序列 Ⅰ
c++·算法·leetcode·周赛·lenyiin
郭wes代码5 小时前
Cmd命令大全(万字详细版)
python·算法·小程序