当前位置: 首页 > article >正文

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 

写在最后

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


http://www.kler.cn/news/330725.html

相关文章:

  • 如何理解矩阵的复数特征值和特征向量?
  • 【60天备战2024年11月软考高级系统架构设计师——第35天:系统安全设计——安全设计模式】
  • quiz: python网络爬虫之规则1
  • 【H2O2|全栈】关于CSS(8)CSS3扩充了哪些新鲜的东西?
  • ISP下载,IAP,ICP,USB转TTL下载SWIM、DAP-link、CMSIS-DAP、ST-LINK,SPI(通信方式),
  • 计算机视觉学习--目标检测Java开发案例
  • 【ios】---swift开发从入门到放弃
  • 【AIGC】AI时代的数据安全:使用ChatGPT时的自查要点
  • 【MySQL 07】内置函数
  • Pikachu-Sql Inject-搜索型注入
  • Python对数据库(MySQL,redis、MongoDB)的操作
  • 24.2.29蓝桥杯|单位换算--8道题
  • 【4.7】图搜索算法-DFS和BFS解根到叶子节点数字之和
  • Linux中的软硬链接和动静态库
  • 大模型压缩3种方式;模型大小的计算;知识蒸馏:利用教师的输入输出,训练调整学生的小模型
  • Linux 中的 Makefile 伪目标详解
  • 【Spring Boot 入门三】Spring Boot与数据库集成 - 构建数据驱动的应用
  • 版本控制-git
  • uniapp中检测应用更新的两种方式-升级中心之uni-upgrade-center-app
  • 产品经理的学习