C++笔记-C++11(一)

news2025/6/6 11:16:09

1.C++11的发展历史

C++11 是 C++ 的第⼆个主要版本,并且是从 C++98 起的最重要更新。它引⼊了⼤量更改,标准化了既有实践,并改进了对 C++ 程序员可⽤的抽象。在它最终由 ISO 在 2011 年 8 ⽉ 12 ⽇采纳前,⼈们曾使⽤名称“C++0x”,因为它曾被期待在 2010 年之前发布。C++03 与 C++11 期间花了 8 年时间,故⽽这是迄今为⽌最⻓的版本间隔。从那时起,C++ 有规律地每 3 年更新⼀次。
2.列表初始化
2.1C++98传统的{}
C++98中的一般数组和结构体可以用{}进行初始化,而在C++11中对{}进行了延伸。
2.2C++11中的{}
1.C++11以后想统⼀初始化⽅式,试图实现⼀切对象皆可⽤{}初始化,{}初始化也叫做列表初始化。
2.内置类型⽀持,⾃定义类型也⽀持,⾃定义类型本质是类型转换,中间会产⽣临时对象,最后优化了以后变成直接构造。
3.{}初始化的过程中,可以省略掉=
4.C++11列表初始化的本意是想实现⼀个⼤统⼀的初始化⽅式,其次他在有些场景下带来的不少便
利,如容器push/inset多参数构造的对象时,{}初始化会很⽅便。
这就是C++11中对内置类型的支持,不过我们在日常使用中也不怎么这样用,这种了解一下即可。
主要是对自定义类型的支持有很大的改变:
 
这里我们创建一个Date类,此时我们就可以用第二张图的方式进行初始化。
这里本质是{2025,1,1}构造了一个Date的临时对象,临时对象又通过拷贝构造赋值给d1,但是我们之前也讲过,这里编译器会优化为直接构造:
可以看出并没有调用拷贝构造函数,只调用了构造函数。
像这种d2引用的就是{2024,7,25}产生的临时对象,这里加上const也是因为引用本身可以被修改,而临时对象具有常性,不能被修改,所以加上const就可以使引用的权限被缩小,变得不能被修改。
这里还需要注意的是在C++98中支持单参数的隐式类型转换,并且可以不加{}。
=符号在C++11中也是可以省略的,这种就看个人习惯了,但是必须要有{}的情况下才可以省略=符号。
像这种没有{},程序就会报错。
相较于有名对象和匿名对象传参,{}传参更有性价比。
2.3C++11中的initializer_list
上面的初始化已经很方便,但是初始化参数的数量取决于你定义的成员变量的个数,简单来说有数量限制,所以对于容器初始化还是不太方便, ⽐如⼀个vector对象,我想⽤N个 值去构造初始化,那么我们得实现很多个构造函数才能⽀持, vector<int> v1 = {1,2,3};vector<int> v2 = {1,2,3,4,5};
这样写起来就太麻烦了,故 C++11库中提出了⼀个std::initializer_list的类, auto il = { 10, 20, 30 }; // the  type of il is an initializer_list ,这个类的本质是底层开⼀个数组,将数据拷⻉ 过来,std::initializer_list内部有两个指针分别指向数组的开始和结束。
通过调试我们可以看出 initializer_list中有两个指针_First和_Last来指向数组的开始和结束。
容器⽀持⼀个std::initializer_list的构造函数,也就⽀持任意多个值构成的 {x1,x2,x3...} 进⾏
初始化。STL中的容器⽀持任意多个值构成的 {x1,x2,x3...} 进⾏初始化,就是通过std::initializer_list的构造函数⽀持的。
并且 initializer_list是支持迭代器访问的,我们通过打印出迭代器的地址和栈上数据地址的比较可以看出,initializer_list所开辟的数组是在栈上的。
这里拿vector容器来演示,就可以通过 initializer_list来进行初始化,不过v1和v2在写法语义是不太一样的,v1是直接构造,v2是构造临时对象+临时对象拷贝复制v2,但是这步操作会被编译器优化为直接构造,这点大家要弄清楚。
而v3引用加const依旧是权限的问题,这里就不过多赘述了。
3.右值引用和移动语义
C++98的C++语法中就有引⽤的语法,⽽C++11中新增了右值引⽤语法特性,C++11之后我们之前学习的引⽤就叫做左值引⽤。⽆论左值引⽤还是右值引⽤,都是给对象取别名。
而在学习右值引用之前我们先认识一下左值和右值。
3.1左值和右值
左值 是⼀个表⽰数据的表达式(如变量名或解引⽤的指针),⼀般是有持久状态,存储在内存中,我
们可以获取它的地址,左值可以出现赋值符号的左边,也可以出现在赋值符号右边。定义时const
修饰符后的左值,不能给他赋值,但是可以取它的地址。
上面就是我们常见的左值,是可以取地址的。
右值 也是⼀个表⽰数据的表达式,要么是字⾯值常量、要么是表达式求值过程中创建的临时对象
等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。
而这些就是右值的一些例子,并且右值是不可以取地址的,如果取地址就会报错。
说了这么多,那么右值该如何人判断呢?
一般有三种情况属于右值:
1.字面值常量:也就是内置类型,如:int,double,char等
2.临时对象:如上面的fmin函数调用,就会产生临时对象,而产生临时对象一般有类型转换,函数返回值/调用,表达式三种情况
3.匿名对象:最后的string就是匿名对象
值得⼀提的是,左值的英⽂简写为lvalue,右值的英⽂简写为rvalue。传统认为它们分别是left
value、right value 的缩写。现代C++中,lvalue 被解释为loactor value的缩写,可意为存储在内
存中、有明确存储地址可以取地址的对象,⽽ rvalue 被解释为 read value,指的是那些可以提供
数据值,但是不可以寻址,也就是说左值和右值的核⼼区别就是能否取地址。
3.2左值引用和右值引用
Type& r1 = x; Type&& rr1 = y; 第⼀个语句就是左值引⽤,左值引⽤就是给左值取别
名,第⼆个就是右值引⽤,同样的道理,右值引⽤就是给右值取别名。
上图就是左值引用和右值引用的基本使用。
那么左值引用能否引用右值或者右值引用能否引用左值呢?
答案是可以的, 左值引⽤不能直接引⽤右值,但是const左值引⽤可以引⽤右值;右值引⽤不能直接引⽤左值,但是右值引⽤可以引⽤move(左值)。
左值引用加const可以引用右值,这就解释了为什么前面文章中的内容我在实现时参数都为加const的左值引用,就是可以让其即可以传左值,也可以传右值。
右值引用引用左值需要用到的move函数:
move是库⾥⾯的⼀个函数模板,move的作用简单来说就是强制类型转换:
其作用就和这样写一样。
注意: 变量表达式都是左值属性,也就意味着⼀个右值被右值引⽤绑定后,右值引⽤变量 表达式的属性是左值,也就是说一个右值引用引用一个右值后,这个右值引用变量就变成左值了。
语法层⾯看,左值引⽤和右值引⽤都是取别名,不开空间。从汇编底层的⻆度看上面代码中r1和rr1
汇编层实现,底层都是⽤指针实现的,没什么区别。底层汇编等实现和上层语法表达的意义有时是
背离的,所以不要然到⼀起去理解,互相佐证,这样反⽽是陷⼊迷途。
3.3引用延长生命周期
我们知道临时对象和匿名对象生命周期都只有当前那一行,到了下一行就会被销毁。
如果不能延长其生命周期的话,上图中的r2和r3不就变成了野引用,所以引用可以延长生命周期。
右值引⽤可⽤于为临时对象延⻓⽣命周期,const 的左值引⽤也能延⻓临时对象⽣存期,但这些对象⽆法被修改。
而被延长的临时对象生命周期就会和表达式变量一样,也就是和r2,r3一样,在main函数结束时才会被销毁。
3.4左值和右值的参数匹配
大家可以想一下这里调用的都是什么函数。
答案就如上图所示,和函数模板那里很相似,没有最适合的时,就用能用的,一旦有最合适的,就用最合适的,所以这里传过去的右值都会调用右值引用的函数。
再看这两个函数应该调用那些函数?
可以看出结果一个调用了左值引用的函数,一个调用了右值引用的函数。
原因上面已经说过,x在引用右值后就变为左值了,再使用move函数就将其强制类型转化了。
右值引⽤变量在⽤于表达式时属性是左值,这个设计这⾥会感觉跟怪,下⼀⼩节我们讲右值引⽤的
使⽤场景时,就能体会这样设计的价值了。
3.5右值引用和移动语义的使用场景
3.5.1左值引用的主要使用场景
左值引⽤主要使⽤场景是在函数中左值引⽤传参和左值引⽤传返回值时减少拷⻉,同时还可以修改实参和修改返回对象的价值。左值引⽤已经解决⼤多数场景的拷⻉效率问题,但是有些场景不能使⽤传左值引⽤返回,如上面的addStrings和generate函数,C++98中的解决⽅案只能是被迫使⽤输出型参数解决。那么C++11以后这⾥可以使⽤右值引⽤做返回值解决吗?显然是不可能的,因为这⾥的本质是返回对象是⼀个局部对象,函数结束这个对象就析构销毁了,右值引⽤返回也⽆法概念对象已经析构销毁的事实。
上面两个函数在c++98时期这样写代价是非常大的,我们上面说过函数返回值会产生临时对象,这时就会调用拷贝构造函数来开辟新的空间在把数据一个个复制过去,而如果要将其返回值赋值给一个变量,那么又要重复上面的操作来进行,所以效率是很低的,而下面右值引用的使用场景就解决了这个问题。
3.5.2移动构造和移动赋值
移动构造函数是⼀种构造函数,类似拷⻉构造函数,移动构造函数要求第⼀个参数是该类类型的引
⽤,但是不同的是要求这个参数是右值引⽤,如果还有其他参数,额外的参数必须有缺省值,一般我们也不会传其它的参数。
移动赋值是⼀个赋值运算符的重载,他跟拷⻉赋值构成函数重载,类似拷⻉赋值函数,移动赋值函
数要求第⼀个参数是该类类型的引⽤,但是不同的是要求这个参数是右值引⽤。
在讲之前我们先看没有移动构造的情况:
这里我们自己实现了一个string类,就和前面string章节写的一样,所以这里就不再演示。
这是没有移动构造之前的方式,两次深拷贝+两次析构释放。
因为编译器会进行优化,所以在vs编译器下我们看不到拷贝构造函数的调用,下面我们通过linux来观察:
这里就是在linux下关闭编译器的优化就会显示拷贝构造的调用了,通过上面的图我们也可以看出没有移动构造的情况下和我们上面说的一样,两次拷贝构造+两次析构。
说了这么多,移动构造该如何写?又是怎么发挥作用的呢?
这就是移动构造的写法,和我们的现代写法一样,直接交换两个string的指针即可,不需要再额外开辟空间,一个个再将数据复制过去。
我们再来看有了移动构造之后的过程:
 
此时的拷贝构造就都变为了移动构造,可能有人会疑惑:传参的移动构造我能理解,毕竟是右值,但是为什么返回值str也会去调用移动构造呢?
这里就要解释一下:编译器会自动将str识别为右值,这点大家记着即可,也没有办法解释,编译器就是这样用的。
到这里大家就可以设想一下有了移动构造之后效率会比没有高很多,所以c++11之后就完美解决了c++98的问题,既不用开辟新的空间,产生新的资源,效率也高很多。
我们再来看移动赋值:
移动赋值和移动构造的思路是一样的,也是利用swap函数交换即可。
这种情况下就要调用=符号重载来实现赋值,vs编译器下的就不展示了,被编译器优化后也看不出来什么,这里就直接展示linux环境:
这是没有使用移动构造和移动复制的情况下,可以看出调用了拷贝构造和=符号的拷贝赋值。
这是使用移动构造和移动复制的情况下,此时就不再调用拷贝构造和拷贝赋值,和移动构造一样,移动赋值同样大大提高了效率。
讲了移动构造和移动赋值,我们回到上面我们感觉很奇怪的点,为什么右值引用变量会变为左值?
我们思考一下,右值一般来说是不能被改变的,不管是临时对象还是匿名对象,都具有常性,那么怎么能交换它们的资源呢?
当时的语法也是遇到这样的问题,这和右值的概念相悖,所以才有了变量表达式都为左值的规定,这样才能交换它们的的资源。
以上就是C++11(一)的内容。

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

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

相关文章

JVM 类初始化和类加载 详解

类初始化和类加载 类加载的时机 加载、验证、准备、初始化和卸载这五个阶段的顺序是确定的&#xff0c;类型的加载过程必须按照这种顺序按部就班地开始&#xff0c;而解析阶段则不一定&#xff1a;它在某些情况下可以在初始化阶段之后再开始&#xff08;懒解析&#xff09;&am…

B站缓存视频数据m4s转mp4

B站缓存视频数据m4s转mp4 结构分析 结构分析 在没有改变数据存储目录的情况下&#xff0c;b站默认数据保存目录为&#xff1a; Android->data->tv.danmaku.bili->download每个文件夹代表一个集合的视频&#xff0c;比如&#xff0c;我下载的”java从入门到精通“&…

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_天气预报日历示例(CalendarView01_18)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

【机器学习】主成分分析 (PCA)

目录 一、基本概念 二、数学推导 2.1 问题设定&#xff1a;寻炸最大方差的投影方向 2.2 数据中心化 2.3 目标函数&#xff1a;最大化投影后的方差 2.4 约束条件 2.5 拉格朗日乘子法 ​编辑 2.6 主成分提取 2.7 降维公式 三、SVD 四、实际案例分析 一、基本概念 主…

二叉树-104.二叉树的最大深度-力扣(LeetCode)

一、题目解析 这里需要注意根节点的深度是1&#xff0c;也就是说计算深度的是从1开始计算的 二、算法原理 解法1&#xff1a;广度搜索&#xff0c;使用队列 解法2&#xff1a;深度搜索&#xff0c;使用递归 当计算出左子树的深度l&#xff0c;与右子树的深度r时&#xff0c;…

物料转运人形机器人适合应用于那些行业?解锁千行百业的智慧物流革命

当传统物流设备困于固定轨道&#xff0c;当人力搬运遭遇效率与安全的天花板&#xff0c;物料转运人形机器人正以颠覆性姿态重塑产业边界。富唯智能凭借GRID大模型驱动的"感知-决策-执行"闭环系统&#xff0c;让物料流转从机械输送升级为智慧调度——这不仅是工具的革…

时序预测模型测试总结

0.背景描述 公司最近需要在仿真平台上增加一些AI功能&#xff0c;针对于时序数据&#xff0c;想到的肯定是时序数据处理模型&#xff0c;典型的就两大类&#xff1a;LSTM 和 tranformer 。查阅文献&#xff0c;找到一篇中石化安全工程研究院有限公司的文章&#xff0c;题目为《…

第四十五天打卡

知识点回顾&#xff1a; tensorboard的发展历史和原理 tensorboard的常见操作 tensorboard在cifar上的实战&#xff1a;MLP和CNN模型 效果展示如下&#xff0c;很适合拿去组会汇报撑页数&#xff1a; 作业&#xff1a;对resnet18在cifar10上采用微调策略下&#xff0c;用tensor…

springboot mysql/mariadb迁移成oceanbase

前言&#xff1a;项目架构为 springbootmybatis-plusmysql 1.部署oceanbase服务 2.springboot项目引入oceanbase依赖&#xff08;即ob驱动&#xff09; ps&#xff1a;删除原有的mysql/mariadb依赖 <dependency> <groupId>com.oceanbase</groupId> …

npm install 报错:npm error: ...node_modules\deasync npm error command failed

npm install 时报错如下&#xff1a; 首先尝试更换node版本&#xff0c;当前node版本20.15.0&#xff0c;更换node版本为16.17.0。再次执行npm install安装成功

Filebeat收集nginx日志到elasticsearch,最终在kibana做展示(二)

EFK 项目需求是要将 一天或15分钟内 搜索引擎抓取网站次数做个统计&#xff0c;并且 如 200 301 404 状态码 也要区分出来, 访问 404 报错的 url 也要截取出来 前期 收集数据 看这篇文章&#xff0c;点击跳转 收集数据完成之后&#xff0c;使用下面方法做展示 创建一个 仪表…

halcon c# 自带examples报错 Matching

最近开始学习halcon与C#的联合编程&#xff0c;打开Matching例程时遇到了下面的问题 “System.TypeInitializationException”类型的未经处理的异常在 halcondotnet.dll 中发生 “HalconDotNet.HHandleBase”的类型初始值设定项引发异常。 System.TypeInitializationExceptio…

服务器重启后配置丢失怎么办?

服务器重启后配置丢失是一个常见问题&#xff0c;特别是在云服务器或容器环境中&#xff0c;若未正确保存或持久化配置&#xff0c;系统重启后就会恢复默认状态。下面是问题分析 解决方案&#xff1a; &#x1f9e0; 一、常见原因分析 原因描述❌ 配置保存在临时目录如 /tmp、…

湖北理元理律所债务优化实践:法律技术与人文关怀的双轨服务

一、债务优化的法律逻辑与生活平衡 在债务重组领域&#xff0c;专业机构需同时解决两个核心问题&#xff1a; 法律合规性&#xff1a;依据《民法典》第680条、第671条&#xff0c;对高息债务进行合法性审查&#xff1b; 生活可持续性&#xff1a;根据债务人收入设计分期方案…

Springboot——整合websocket并根据type区别处理

文章目录 前言架构思想项目结构代码实现依赖引入自定义注解定义具体的处理类定义 TypeAWebSocketHandler定义 TypeBWebSocketHandler 定义路由处理类配置类&#xff0c;绑定point制定前端页面编写测试接口方便跳转进入前端页面 测试验证结语 前言 之前写过一篇类似的博客&…

Qiskit:量子计算模拟器

参考文献&#xff1a; IBM Qiskit 官网Qiskit DocumentationQiskit Benchpress packageQiskit Algorithms package量子计算&#xff1a;基本概念常见的几类矩阵&#xff08;正交矩阵、酉矩阵、正规矩阵等&#xff09;Qiskit 安装指南-博客园使用Python实现量子电路模拟&#x…

龙虎榜——20250605

上证指数放量收阳线&#xff0c;个股涨跌基本持平&#xff0c;日线持续上涨。 深证指数放量收阳线&#xff0c;日线持续上涨。 2025年6月5日龙虎榜行业方向分析 1. 通信设备 代表标的&#xff1a;生益电子、三维通信、瑞可达 驱动逻辑&#xff1a;5.5G商用牌照发放预期加速&…

残月个人拟态主页

TwoMicry个人主页 残月个人拟态主页 原项目作者&#xff1a;KAI GE 在此基础上进行二次修改 精简重构一下 项目简介&#xff1a; 一个精美的拟态风格个人主页&#xff0c;采用现代化的玻璃拟态设计和丰富的动画效果 主要特色&#xff1a; 视觉效果&#xff1a; – 玻璃…

热门消息中间件汇总

文章目录 前言RabbitMQ基本介绍核心特性适用场景 Kafka基本介绍核心特性适用场景 RocketMQ基本介绍核心特性适用场景 NATS基本介绍核心特性适用场景 总结选型建议与未来趋势选型建议未来趋势 结语 前言 大家后&#xff0c;我是沛哥儿。作为技术领域的老湿机&#xff0c;在消息…

AiPy实战:10分钟用AI造了个音乐游戏!

“在探索AI编程边界时&#xff0c;我尝试了一个实验&#xff1a;能否让自然语言指令直接生成可交互的音乐学习应用&#xff1f;作为新一代智能编程协作框架&#xff0c;AiPy展示了对开发意图的深度理解能力——当输入创建钢琴学习游戏&#xff0c;包含动态难度关卡和即时反馈系…