C++11 新特性 decltype 说明符
一、typeof与typeid
1.1、typeof
在C++11标准之前,GCC已经提供了一个类似功能的运算符 typeof
对类型进行推导,但是这毕竟是编译器的实现,不是标准。
int a = 0;
typeof(a) b = 5;
1.2、typeid
C++标准提供了 typeid
运算符,获取的类型信息会包含在一个类型为std::type_info
的对象里,可以调用成员函数name
获取其类型名。
int x1 = 0;
double x2 = 5.5;
std::cout << typeid(x1).name() << std::endl;
std::cout << typeid(x1 + x2).name() << std::endl;
std::cout << typeid(int).name() << std::endl;
成员函数name
返回的类型名在C++标准中并没有明确的规范,所以输出的类型名会因编译器而异。
-
typeid
的返回值是一个左值,生命周期直到当前函数周期结束 -
typeid
返回的std::type_info
删除了复制构造函数,若想保存std::type_info
,只能获取其引用或者指针-
auto t1 = typeid(int); // 编译失败,没有复制构造函数无法编译auto &t2 = typeid(int); // 编译成功,t2推导为const std::type_info&auto t3 = &typeid(int); // 编译成功,t3推导为const std::type_info*
-
-
typeid
的返回值总是忽略类型的 cv 限定符,也就是typeid(const T) == typeid(T))
。
很明显,typeid有很大缺陷,它并不能像typeof
那样在编译期就确定对象类型。
二、decltype
为了用统一方法解决上述问题,C++11标准引入了decltype
说明符,使用decltype
说明符可以获取对象或者表达式的类型,其语法与typeof
类似:
int x1 = 0;
decltype(x1) x2 = 0;
std::cout << typeid(x2).name() << std::endl; // x2的类型为intdouble x3 = 0;
decltype(x1 + x3) x4 = x1 + x3;
std::cout << typeid(x4).name() << std::endl; // x1+x3的类型为doubledecltype({1, 2}) x5; // 编译失败,{1, 2}不是表达式
为了更好的讨论decltype
的优势,需要用到返回类型后置。
auto sum(int a1, int a2)->int {return a1+a2;
}
上述代码中,以C++11为标准,auto
作为占位符并不能使编译器对函数返回类型进行推导,必须使用返回类型后置的形式指定返回类型。如果想泛化这个函数,就需要用到函数模板
template<class R, class T1, class T2>
R sum(T1 a1, T2 a2) {return a1 + a2;
}auto x3 = sum<double>(5, 10.5);
满足泛化sum
函数的要求,但必须为函数模板指定返回值类型。如何在编译期完成所有的类型推导工作?
template<class T1, class T2>
auto sum(T1 a1, T2 a2)->decltype(a1 + a2) {return a1 + a2;
}auto x4 = sum(5, 10.5);
decltype
完美地解决了之前需要指定返回类型的问题。在实例化sum
函数的时候,编译器就能够知道sum
的返回类型了。
C++14标准中,直接支持了对
auto
声明的返回类型进行推导template<class T1, class T2> auto sum(T1 a1, T2 a2) {return a1 + a2; }
但是
auto
还存在一些小问题template<class T> auto return_ref(T& t) {return t; }int x1 = 0; static_assert(std::is_reference_v<decltype(return_ref(x1))>// 编译错误,返回值不为引用类型 );
上述代码中
auto
直接被推导为值类型(使用auto
声明变量初始化时,目标对象如果是引用,则引用属性会被忽略),导致编译错误,
三、推导规则
decltype(e)
(其中e
的类型为T
)
1. 如果
e
是一个未加括号的标识符表达式(结构化绑定除外)或者未加括号的类成员访问,则decltype(e)
推断出的类型是e
的类型T
。如果并不存在这样的类型,或者e
是一组重载函数,则无法进行推导。2.如果
e
是一个函数调用或者仿函数调用,那么decltype(e)
推断出的类型是其返回值的类型。3.如果
e
是一个类型为T
的左值,则decltype(e)
是T&
。4.如果
e
是一个类型为T
的将亡值,则decltype(e)
是T&&
。5.除去以上情况,则
decltype(e)
是T
。
看几个例子
const int&& foo();
int i;
struct A {double x;
};
const A* a = new A();decltype(foo()); // decltype(foo())推导类型为const int&& 满足规则4
decltype(i); // decltype(i)推导类型为int 满足规则1
decltype(a->x); // decltype(a->x)推导类型为double 满足规则1
decltype((a->x)); // decltype((a->x))推导类型为const double& 满足规则3,加了括号就是表达式,表达式返回左值,还有const修饰,所以 (a->x) 的类型是 const double&,即指向 x 的常量引用。int i;
int *j;
int n[10];
decltype(i=0); // 推导类型为int& 表达式返回左值
decltype(0,i); // 推导类型为int& 逗号表达式,返回第二个值
decltype(i,0); // 推导类型为int
decltype(n[5]); // 推导类型为int& 数组n中的第6个元素,左值
decltype(*j); // 推导类型为int& 左值
decltype(static_cast<int&&>(i)); // 推导类型为int&& 将亡值
decltype(i++); // 推导类型为int 右值
decltype(++i); // 推导类型为int& 左值
decltype("hello world"); // 推导类型为const char(&)[12] 常量数组左值
四、CV限定符
通常情况下,decltype(e)
所推导的类型会同步e
的cv
限定符,cv限定符这里是指onst
和volatile
关键字
const int i = 0;
decltype(i); // 推导类型为const int
当e
是未加括号的成员变量时,父对象表达式的cv
限定符会被忽略,不能同步到推导结果:
struct A {double x;
};
const A* a = new A();
decltype(a->x); // 推导类型为double, const属性被忽略
decltype((a->x)); // 推导类型为const double&, const属性不被忽略
相关文章:
C++11 新特性 decltype 说明符
一、typeof与typeid 1.1、typeof 在C11标准之前,GCC已经提供了一个类似功能的运算符 typeof对类型进行推导,但是这毕竟是编译器的实现,不是标准。 int a 0; typeof(a) b 5;1.2、typeid C标准提供了 typeid 运算符,获取的类型…...

java线程局部变量使用方式
线程局部变量是Java中用于存储线程本地信息的变量。这种变量仅在线程的生命周期内存在,并且每个线程都有自己的一份拷贝。换句话说,线程局部变量是线程私有的,其他线程无法访问。 使用场景主要包括: 1. 存储线程状态信息ÿ…...
【隧道篇 / WAN优化】(7.4) ❀ 01. 启动WAN优化 ❀ FortiGate 防火墙
【简介】几乎所有的人都知道,防火墙自带的硬盘是用来保存日志,以方便在出现问题时能找到原因。但是很少的人知道,防火墙自带的硬盘其实还有另一个功能,那就是用于WAN优化。 防火墙自带的硬盘 在FortiGate防火墙A、B、C、D系列&…...

2024数维杯数学建模B题生物质和煤共热解问题的研究原创论文分享
大家好,从昨天肝到现在,终于完成了2024数维杯数学建模挑战赛B题的完整论文啦。 实在精力有限,具体的讲解大家可以去讲解视频: 2024数维杯数学建模B题煤共热解每一问高质量完整代码讲解!_哔哩哔哩_bilibili 2024数维杯…...
中国电子学会(CEIT)2022年12月真题C语言软件编程等级考试三级(含详细解析答案)
中国电子学会(CEIT)考评中心历届真题(含解析答案) C语言软件编程等级考试一级 2022年12月 编程题五道 总分:100分一、鸡兔同笼(20分) 一个笼子里面关了鸡和兔子(鸡有2只脚,兔子有4只脚,没有例外)。已经知道了笼子里面脚的总数a,问笼子里面至少有多少只动物,至…...

今日早报 每日精选15条新闻简报 每天一分钟 知晓天下事 5月12日,星期日
每天一分钟,知晓天下事! 2024年5月12日 星期日 农历四月初五 1、 全国多地已推“一次挂号管三天”,部分医院专家门诊适用。 2、 在梅大高速塌方事故中拦车、救援,黄曼秋等5人拟确认为见义勇为。 3、 深圳新能源车指标申请条件调…...

微服务思想以及实现
文章目录 前言一、什么时候需要拆分微服务1. 创业型项目2. 大型项目 二、怎么拆1. 拆分目标2. 拆分方式 三、微服务之间远程调用1. 实现方式2. 手动发送Http请求(RestTemplate)3. 服务注册中心3.1 原理3.2 Nacos注册中心3.3 服务注册3.4 服务发现(Discov…...
C语法:格式符号%f和%lf引发的错误
今天编程时有如下代码: #include"stdio.h"int main(void) {double profit;double bonus;printf("请输入本月利润\n");scanf("%f",&profit);//错误:此行profit是double类型,格式符为%f,当输入8时࿰…...

Java基础入门day48
day48 JDBC调用关系 tomcat 简介 tomcat是Apache下的一个核心项目,免费开源,支持servlet和jsp。 tomcat技术先进,性能稳定,目前比较流行的web应用服务器 安装 官网: Apache Tomcat - Welcome! 下载 tomcat8.5 解压&a…...

C++笔记(体系结构与内核分析)
1.OOP面向对象编程 vs. GP泛型编程 OOP将data和method放在一起,目的是通过封装、继承、多态提高软件的可维护性和可扩展性GP将data和method分开,可以将任何容器与任何算法结合使用,只要容器满足塞饭所需的迭代器类型 2.算法与仿函数的区别 …...
c++ 唤醒指定线程
在C中,直接唤醒一个特定的线程并不像在Java的Thread类中有interrupt()方法或者某些操作系统特定的API(如POSIX的pthread_cond_signal或Windows的SetEvent)那样简单。C标准库没有提供一个直接的方法来"唤醒"一个正在等待的线程。然而…...

java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
今天遇到一个问题 系统线上问题,经常出现这样的问题,刚重启系统时不报错了,可是运行一段时间又会出现。sql已经写了limit 1,mybatis的debug日志也返回total为1,可是却报错返回了1805条数据 乍一看,感觉太不…...

AI图书推荐:利用生成式AI实现业务流程超自动化
《利用生成式AI实现业务流程超自动化》(Hyperautomation with Generative AI)这本书探索了广泛的用例和示例,展示了超自动化在不同行业、领域和特定部门的多样化应用, 让您熟悉UiPath、Automation Anywhere和IBM等流行工具和平台&…...
什么事防抖和节流,有什么区别,如何实现
防抖和节流,本质上是优化高频率执行代码的一种手段,比如:resize、scroll、keypress、mousemove这些事件在触发的时候,会不断调用绑定在事件上的回调函数,这样极大浪费资源,降低前端性能。 为了优化体验&am…...
PanguSync大数据量初始化脚本
由于数据库增量同步软件PanguSync初始化最大超时时间为600s,如果初始数据量很大,第一次部署时可能会超时,可以先停止任务,使用以下Sql语句进行初始化,以下语句可以分步执行,初始化完成后,后续无需再执行耗时…...

DELL T630服务器iDRAC分辨率调整办法
对于Dell T630服务器的iDRAC分辨率调整,您需要登录到iDRAC的Web界面。以下是详细的步骤: 登录iDRAC:在浏览器中输入iDRAC的IP地址,然后使用用户名(通常是“root”)和密码登录。 导航到虚拟控制台ÿ…...
您真的会高效使用 Mac 吗?
文章目录 屏幕的保养快捷键预览修改文件名查看文件属性搜索编辑复制,粘贴,剪切,撤销删除 跳转窗口屏幕截图声音Dock强制退出查字典神奇的Option键鼠标与触控板切换桌面与应用程序打开通知中心打开Mission Control 安装与卸载Mac应用程序压缩和…...
Vue11 Vue3完结撒花
shallowRef和shallowReactive shallowRef 作用:创建一个响应式数据,但只对顶层属性进行响应式处理 用法 let myVar shallowRef(initialValue)特点:只跟踪引用值变化,不关心值内部的属性变化 案例 <template><div c…...
CodeTop 高频笔试题总结(持续更新)
🏆 频率从高到低排序 👨🏫 参考的频率数据:CodeTop 👨🏫 力扣hot100 无重复字符的最长子串 双指针 滑动窗口 哈希👨🏫 力扣hot100 反转链表 指针 递归 一题多解👨…...

类和对象一(从封装开始讲述)
目录: 一.封装 二.封装扩展之包,自定义包 三.访问限定符 四.static成员 一.封装:封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行 交互。面向对象…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...

向量几何的二元性:叉乘模长与内积投影的深层联系
在数学与物理的空间世界中,向量运算构成了理解几何结构的基石。叉乘(外积)与点积(内积)作为向量代数的两大支柱,表面上呈现出截然不同的几何意义与代数形式,却在深层次上揭示了向量间相互作用的…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
python打卡第47天
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 def visualize_attention_map(model, test_loader, device, class_names, num_samples3):"""可视化模型的注意力热力图,展示模…...
shell脚本质数判断
shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数)shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数) 思路: 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...

Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...

持续交付的进化:从DevOps到AI驱动的IT新动能
文章目录 一、持续交付的本质:从手动到自动的交付飞跃关键特性案例:电商平台的高效部署 二、持续交付的演进:从CI到AI驱动的未来发展历程 中国…...