【C++】深入理解decltype和decltype(auto)

深入理解decltype和decltype(auto)

  • 一、decltype语法介绍
  • 二、decltype的推导规则
    • 1. expr不加括号
    • 2. expr加上括号
  • 三、关于decltype的CV属性推导
  • 四、 decltype(auto) 的使用

一、decltype语法介绍

decltype关键字是C++11新标准引入的关键字,它和关键字auto的功能类似,也可以自动推导出给定表达式的类型,但它和auto的语法有些不同,auto推导的表达式放在=的右边,并作为auto所定义的变量的初始值,而decltype是和表达式结合在一起,语法如下:

decltype(expr) var;

它的语法像是函数调用,但它不是函数调用而是运算符,和sizeof运算符类似,在编译期间获取他的类型,表达式expr不会被真正执行,因此不会产生汇编代码。

decltypeauto在功能上大部分相似,但推导规则和应用场景存在一些区别:

  • auto定义变量时必须提供初始值表达式,利用初始值表达式推导出类型并用它作为变量的初始值,使用auto作为值语义的推导时,会忽略表达式expr的引用性CV属性
  • decltype定义变量时可以不需要初始值。还有decltype可以保留引用性CV属性
  • 引用性:表达式的引用属性,如左值引用或者右值引用。
  • CV 属性:指的是 const 和 volatile 修饰符。它们用于修饰类型,以指定对象的特殊属性和行为。

二、decltype的推导规则

decltype的推导规则主要有三条规则:

  • 如果 expr 一个类成员访问表达式,或者是一个单独的变量,decltype(expr) 的类型就和 expr 一致,这是最普遍最常见的情况。
  • 如果 expr 是函数调用,那么 decltype(expr) 的类型就和函数返回值的类型一致。
  • 如果 expr 是一个左值,或者被括号()包围,那么 decltype(expr) 的类型就是 expr 的引用;假设 expr 的类型为 T,么 decltype(expr) 的类型就是 T&

为了更好地理解 decltype 的推导规则,下面来看几个实际的例子。

1. expr不加括号

#include <iostream>
#include <type_traits>int func(int x) {return x;
}class Base {
public:int x = 0;
};int main()
{// 情况1int i = 1;const int& j = i;decltype(j) x = j;	decltype(i) y = i;// is_same是C++11之后的一个类模板,用于判断两个类型是否一致cout << "x is const int& ? " << std::boolalpha << std::is_same<decltype(x), const int&>::value << endl;cout << "y is int ? " << std::boolalpha <<std::is_same<decltype(y), int>::value << endl;const Base b;cout << "decltype(b.x) is int ? " << std::boolalpha << std::is_same<decltype(b.x), int>::value << endl;int  x1 = 1, x2 = 2;cout << "decltype(x1 + x2) is int ? " << std::boolalpha << std::is_same<decltype(x1 + x2), int>::value << endl;cout << "decltype(x1, x2) is int ? " << std::boolalpha <<std::is_same<decltype(x1, x2), int>::value << endl;cout << "decltype(x1, 0) is int ? " << std::boolalpha << std::is_same<decltype(x1, 0), int>::value << endl;// 情况2cout << "decltype(func(1)) is int ? " << std::boolalpha << std::is_same<decltype(func(1)), int>::value << endl;// 情况3int a[10] = { 0 };cout << "decltype(a[1] is int& ? " << std::boolalpha << std::is_same<decltype(a[1]), int&>::value << endl;return 0;
}

在这里插入图片描述

2. expr加上括号

int main()
{// 情况3int x1 = 1;int x2 = 2;const Base b;cout << "decltype((x1 + x2)) is int ? " << std::boolalpha << std::is_same<decltype((x1 + x2)), int>::value << endl;cout << "decltype((x1)) is int& ? " << std::boolalpha << std::is_same<decltype((x1)), int&>::value << endl;cout << "decltype((b.x)) is const int& ? " << std::boolalpha << std::is_same<decltype((b.x)), const int&>::value << endl;return 0;
}

在这里插入图片描述

(1)式中相加后的结果是一个右值,加上括号后依然是一个右值,因此推导结果是int

(2)式中跟之前没有加括号的情况不一样,加上括号相当于是返回x1变量,因此是一个左值,推导结果是一个引用。

(3)式返回的是一个左值,推导结果是一个引用,但因为定义的类对象b是一个const对象,要保持它的内容不可被修改,因此引用要加上const修饰。

三、关于decltype的CV属性推导

  • 通常情况下,decltype(expr)所推导的类型会同步expr的cv限定符
  • expr是未加括号的成员变量时,对象表达式的cv限定符会被忽略
class Base {
public:int x = 0;
};int main()
{// CV限定符的推导const int i = 0;cout << "decltype(i) is const int ? " << std::boolalpha << std::is_same<decltype(i), const int>::value << endl;const Base b;cout << "decltype(b.x) is int ? " << std::boolalpha << std::is_same<decltype(b.x), int>::value << endl;cout << "decltype((b.x)) is const int& ? " << std::boolalpha << std::is_same<decltype((b.x)), const int&>::value << endl;return 0;
}

在这里插入图片描述

为什么decltype((b.x))const int&而不是const int呢?

因为decltype 的第三条推导规则:被括号()包围,会变成引用类型。

写到这里,不得不感概C++的语法是真的难,头都要给我学秃了…… 😭😭😭

四、 decltype(auto) 的使用

decltype(auto) 是 C++14 引入的一种类型推导机制,它结合了 decltypeauto 的特性。

使用 decltype(auto) 表示让auto使用自动类型推导,但推导的规则是按照decltype的规则来推导,这样在推导时会保留表达式的值的引用性和CV属性

decltype(auto)的使用语法规则如下:

decltype(auto) var = expr;
  • 简单使用示例:
int i = 1;
const int& j = i;
decltype(auto) x = j;	// x的类型为const int&
decltype(auto) y = i;	// y的类型为int
  • decltype(auto)用于推导函数返回值的类型
#include <iostream>
#include <vector>std::vector<int> vec = {1, 2, 3, 4, 5};// 返回左值引用
decltype(auto) getElementRef(size_t index) {return vec[index];
}// 返回右值
decltype(auto) getElementValue(size_t index) {return vec[index] + 0;  // 使用右值表达式
}int main() {// 使用 getElementRef 返回左值引用decltype(auto) ref = getElementRef(2);ref = 100;  // 修改引用的值std::cout << "vec[2]: " << vec[2] << std::endl;  // 输出 100// 使用 getElementValue 返回右值decltype(auto) val = getElementValue(2);std::cout << "val: " << val << std::endl;  // 输出 100return 0;
}
  • decltype(auto)使用陷阱

最后,对于decltype(auto)能够推导函数返回值为引用类型这一点,需要提醒一下的是,小心会有下面的陷阱,如下面的函数:

decltype(auto) func() {int x;// do something...return x;
}

这里推导出来的返回值类型是int,并且会拷贝局部变量x的值,这个没有问题。但如果是这样的定义:

decltype(auto) func() {int x;// do something...return (x);
}

这个版本返回的是一个引用,它将引用到一个即将销毁的局部变量上,当这个函数返回后,所返回的引用将引用到一个不存在的变量上,造成引用空悬的问题,程序的结果将是未知的。无论是有意的还是无意的返回一个引用,都要特别小心。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/24850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hadoop3:MapReduce源码解读之Map阶段的Job任务提交流程(1)

3、Job工作机制源码解读 用之前wordcount案例进行源码阅读&#xff0c;debug断点打在Job任务提交时 提交任务前&#xff0c;建立客户单连接 如下图&#xff0c;可以看出&#xff0c;只有两个客户端提供者&#xff0c;一个是YarnClient&#xff0c;一个是LocalClient。 显然&a…

Objective-C 学习笔记 | 基础

Objective-C 学习笔记 | 基础 参考书&#xff1a;《Objective-C 编程&#xff08;第2版&#xff09;》 第1部分 入门 Objective-C语言是以C语言为基础的&#xff0c;但增加了对面向对象编程的支持。Objective-C语言是用来开发在苹果iOS以及OS X操作系统上运行的应用的编程语…

植物大战僵尸杂交版 2.0 下载及配置图文教程

文章目录 Part.I IntroductionPart.II 下载Chap.I 下载地址Chap.II 网盘直链下载 Part.III 配置Chap.I 解压与安装Chap.II 加载存档Chap.III 其他设置 Reference Part.I Introduction 最近看大仙儿直播植物大战僵尸&#xff0c;觉得挺好玩的。它大概长这样&#xff1a; 就上网…

使用proteus仿真51单片机的流水灯实现

proteus介绍&#xff1a; proteus是一个十分便捷的用于电路仿真的软件&#xff0c;可以用于实现电路的设计、仿真、调试等。并且可以在对应的代码编辑区域&#xff0c;使用代码实现电路功能的仿真。 汇编语言介绍&#xff1a; 百度百科介绍如下&#xff1a; 汇编语言是培养…

Python GUI编程:深入探索现代GUI库及其创新应用

目录 引言 Python GUI库概览 1. Tkinter 2. PyQt/PySide 3. wxPython 4. Kivy 5. PyGTK 6.FLTK (pyFLTK) 创新应用案例 1. 交互式数据分析工具 2. 智能物联网(IoT)仪表板 3. 增强现实(AR)辅助设计软件 4. 跨平台的科学计算软件 5. 交互式教育软件 实战示例1&…

.NET MAUI 了解MVVM

MVVM 模式中有三个核心组件&#xff1a;模型、视图和视图模型。 每个组件的用途不同。 下图显示了这三个组件之间的关系。 视图 视图负责定义用户在屏幕上看到的结构、布局和外观。 理想情况下&#xff0c;每个视图在 XAML 中定义&#xff0c;代码隐藏有限&#xff0c;不包含业…

linux shell实现打印国际象棋棋盘

chess.sh #!/bin/bashfor i in {1..8} dofor j in {1..8}dosum$[ij]if [ $[sum%2] -eq 0 ];thenecho -ne "\033[46m \033[0m"elseecho -ne "\033[47m \033[0m"fidoneecho done验证&#xff1a;

微信小程序学习笔记(4)

文章目录 1、< template >< / template >2、样式导入i、wxmlii、wxss 3、flex布局i、容器属性ii、项目属性 1、< template >< / template > 模板可以重复调用 首先要定义一个模板&#xff1a; <template name"test"><view>{{…

AbstractMap和SimpleEntry

一、AbstractMap 位置&#xff1a;在java.util包 二、SimpleEntry 1、概述 继承了Map中的内部接口Entry<K,V> SimpleEntry<K,V>不仅继承了Map.Entry<K,V>&#xff0c;还继承了序列化的接口 2、构造方法 方法说明SimpleEntry(K key,V value)通过键值对初…

RabbitMQ-工作模式(Publish模式Routing模式)

文章目录 发布/订阅&#xff08;Publish/Subscribe&#xff09;交换机临时队列绑定总体代码示例 路由&#xff08;Routing&#xff09;绑定直连交换机多重绑定发送日志订阅总体代码示例 更多相关内容可查看 发布/订阅&#xff08;Publish/Subscribe&#xff09; 构建一个简单的…

vue antdesgin table 动态表头动态数据示例

以下是一个基于 Vue 和 Ant Design Vue 的示例&#xff0c;可以动态生成表格的表头和数据&#xff1a; <template><div><a-button click"addColumn">添加列</a-button><a-table :columns"columns" :dataSource"dataSource…

HC-05蓝牙模块配置连接和使用

文章目录 1. 前期准备 2. 进入AT模式 3. 电脑串口配置 4. 配置过程 5. 主从机蓝牙连接 6. 蓝牙模块HC-05和电脑连接 1. 前期准备 首先需要准备一个USB转TTL连接器&#xff0c;电脑安装一个串口助手&#xff0c;然后按照下面的连接方式将其相连。 VCCVCCGNDGNDRXDTXDTXD…

ICLR24大模型提示(8) | 退一步思考:在大型语言模型中通过抽象引发推理

【摘要】我们提出了一种简单的提示技术&#xff0c;即后退提示法&#xff0c;它使 LLM 能够进行抽象&#xff0c;从包含特定细节的实例中得出高级概念和第一原理。通过使用概念和原理来指导推理&#xff0c;LLM 显著提高了遵循正确推理路径解决问题的能力。我们使用 PaLM-2L、G…

Facebook企业户 | Facebook公共主页经营

Facebook作为社交媒体巨头&#xff0c;拥有庞大的用户基数&#xff0c;因此&#xff0c;有效经营公共主页是获取持续流量、提升客户信任度和粘性、促进产品或服务销售与转化的关键。要优化Facebook主页&#xff0c;关注以下几点&#xff1a; 1、参与度是关键指标&#xff1a;因…

Python YOLOv5 7.0 基于深度学习的口罩检测识别系统

目录 1&#xff0c;演示视频和资源下载 1.1 演示视频 1.2 资源下载 2&#xff0c;数据集 3&#xff0c;代码 3.1 带 PyQt5 UI 的检测程序&#xff0c;基于YOLOv5 7.0 3.1.1 根据训练结果进行检测 3.1.2 自动保存每张图片/每帧的检测结果 3.1.3 筛选查看每张图片/每帧检…

Linux---sudo命令

文章目录 目录 文章目录 一.sudo命令简介 二.sudo 命令的特点 三.sudo 相关文件 四.sudo 命令授权配置 一.sudo命令简介 sudo 命令全称“SuperUser Do”&#xff0c;是Linux系统中的一个命令能够使普通用户以超级用户身份去执行某些命令。 二.sudo 命令的特点 sudo能够授权…

HC05蓝牙模块与笔记本蓝牙连接

文章目录 1. 电脑和蓝牙模块连接 2. 串口软件调试 1. 电脑和蓝牙模块连接 HC05支持SPP协议&#xff0c;使用PC主机自带蓝牙&#xff0c;或者笔记本加蓝牙适配器。与HC05连接后&#xff0c;可在电脑端虚拟出串口&#xff0c;这样上位机软件就可以像操作串口一样与HC05通信。对…

[ROS 系列学习教程] 建模与仿真 - 使用 Arbotix 控制机器人

ROS 系列学习教程(总目录) 本文目录 一、Arbotix 简介二、安装Arbotix三、配置Arbotix控制器四、配置launch启动文件五、数据交互接口六、在rviz中仿真控制机器人6.1 直接发topic控制6.2 使用键盘控制6.3 编写代码控制机器人移动 前面讲了机器人的建模&#xff0c;是静态的&…

二进制中1的个数-java

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、二进制中1的个数 二、算法思路 1.将一个整数转化成二进制形式 2.查询一个数的二进制数中的第k位是多少 3.lowbit(x)操作 三、代码如下 1.代码如下&…

ChatTTS 文字生成语言本地模型部署

ChatTTS部署 官方信息 [ChatTTS首页](https://chattts.com/)搭建步骤 1、下载源码 git clone https://github.com/2noise/ChatTTS.git 2、按照环境 pip install torch ChatTTS pip install -r requirements.txt 3、下载模型 git clone https://www.modelscope.cn/pzc163/ch…