C++——C++11 第一篇

news2024/11/17 2:51:50

目录

 统一的列表初始化

 {}初始化

decltype 

​编辑 nullptr

STL中一些变化

 右值引用和移动语义

 左值引用和右值引用

 总结

左值引用优缺点 

右值引用(将亡值) 

 拷贝赋值和移动赋值

万能引用|完美转发

移动构造和移动赋值注意事项 

delete


 

点击跳转了解C++11

 统一的列表初始化

 {}初始化

 C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自
定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

 

std::initializer_list使用场景:
std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加
std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=
的参数,这样就可以用大括号赋值

把大括号里面的东西给对象,对象就会被认为是initializer_list类型

点击跳转了解

 所有的容器都支持了这样的构造函数,所以我们可以用列表初始化。

调用支持list(initializer_list<value_type>il)类似这样的构造函数

我们自己写的vectoru不支持这种写法 ,因为我们没initializer_list,我们在之前写的vector中这样写,就可以实现C++11这种写法

 有了上面的initializer_list,我们还可以这样写

 v4是隐式类型转换,而且调用了构造函数

map也可以这样写,首先是map支持 initializer_list的构造,而每个数据都是pair,pair支持初始化,调用了pair的构造。

 C++11以后一切对象都可以用列表初始化,但是普通对象最好用以前的方式初始化,容器之类的可以用列表初始化

decltype 

 关键字decltype将变量的类型声明为表达式指定的类型。

y1的类型是由x类型决定,y2的类型由等号右边的值决定,auto和decltype有差异,俩者不一样。 

 nullptr

 由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示
整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。

STL中一些变化

 新容器
用橘色圈起来是C++11中的一些几个新容器,但是实际最有用的是unordered_map和
unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解一下即可。

 

 容器中的一些新方法

都支持initializer_list构造,用来支持列表初始化。
如果我们再细细去看会发现基本每个容器中都增加了一些C++11的方法,但是其实很多都是用得
比较少的。
比如提供了cbegin和cend方法返回const迭代器等等,但是实际意义不大,因为begin和end也是
可以返回const迭代器的,这些都是属于锦上添花的操作。

 array对越界很敏感。实际情况arrar用的很少,因为C语言使用关了。

 右值引用和移动语义

 左值引用和右值引用

 什么是左值?什么是左值引用?

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋
值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边
。定义时const修饰符后的左
值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名。

 

 什么是右值?什么是右值引用?

右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引
用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能
取地址
。右值引用就是对右值的引用,给右值取别名。

 右值不能取地址

 

 左值引用不能去引用右值,加上const就可以

 

所以在函数传参的时候我们如果使用了引用传参,就加const,这样该函数既能接收左值,又能接收右值,若不加const只能加收左值引用,不能引用右值

 右值引用不能直接引用左值,对左值加上move函数,右值引用就可以引用左值了

 此时不报错

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可
以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地
址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感觉很神奇,
这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。
 

 这里rr1和rr2都是左值,因为他们可以进行取地址

 总结

 左值引用总结:

我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。

 1. 左值引用只能引用左值,不能引用右值。
2. 但是const左值引用既可引用左值,也可引用右值

右值引用总结:

右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能
取地址。
1. 右值引用只能右值,不能引用左值。
2. 但是右值引用可以move以后的左值。

左值引用优缺点 

左值引用解决哪些问题:

1.做参数

a.减少拷贝,提高效率   b.做输出型参数

2.做返回值

a.减少拷贝,提高效率  b.引用返回,可以修改返回对象(比如:operator[]). 

缺点:

以to_string为例 ,它是传值返回,简单实现to_string,返回的str是局部对象,出了作用域就会销毁,不能用左值引用返回,如果用左值引用返回此时程序就崩了,因为str已经析构了。

 还有这道杨辉三角的返回值,返回的是vector<vector<int>>,C++98左值引用面对这种场景很难处理

 我们可以这样修改,这种优化的缺点不太符合使用习惯

右值引用(将亡值) 

 C++11的右值引用就能解决上面的问题

这里有俩次string的拷贝构造,编译器优化后只有一次拷贝构造,这里出了作用域str就销毁,所以不能用左值引用返回,我们可以用右值返回

namespace myspace
{
	myspace::string to_string(int value)
	{
		myspace::string str;
		//
		return str;
	}
}
int main()
{
	myspace::string ret = to_string(-3456);
	return 0;
}

 右值引用的提出,产生了移动构造

拷贝构造是左值引用,移动构造是右值引用,右值引用也可以走拷贝构造因为被const所修饰,C++每次在选择函数时,会选择最匹配的函数进行使用,既有左值引用又有右值引用,当使用右值引用时,就会走右值引用

 右值:1.内置类型右值——纯右值(如x+y)  2.自定义类型右值——将亡值(声明周期一般只在那一行或函数结束)

这里s是将亡值,用swap保留s的资源。所以叫移动构造

 

 str1的资源被转移,move(str1)这里吧str1转成了右值,str1就是将亡值,str1的资源就被转移了

 这里之前是一次拷贝构造,现在是一次移动构造,选择最匹配的函数,拷贝构造的代价要大于移动构造的代价,因为拷贝了临时对象之后,还要释放临时对象,移动构造是直接转移资源,不需要拷贝。

 

注释掉移动构造变成了拷贝构造

 左边是拷贝构造(此时没有写移动构造),右边是写了移动构造之后,编译器匹配到了移动构造

 拷贝赋值和移动赋值

 屏蔽掉移动构造之后运行程序。

 

 取消移动构造的注释,加上移动赋值,把s和将亡值进行交换,将亡值在被销毁的时候,会带着之前s的值一并被销毁

 

 右值引用增加了移动构造和移动赋值之后,提高了效率,减少了资源的拷贝和释放,直接把资源进行交换。

 右值引用在延长对象的生命周期,这种说法是错的,因为他转移了资源,并没有延长对象的生命周期

 

 

 这里s1+s2是一个表达式,表达式的值是一个临时值,临时对象是右值(将亡值)

C++11以后提供了移动构造和移动赋值

 STL中所有的插入接口,都有右值引用,解决了用传值返回类型对象的拷贝问题

 这里传匿名对象(匿名对象周期只在那一行),传的是右值(将亡值),这里转移俩次是跟内部实现有关系,这个不需要关注,在这里只需搞清楚移动构造即可

 

万能引用|完美转发

 如果普通参数是这样则成为右值版本,但是在模板里这样使用就会被称作万能引用,引用折叠。

折叠的规则很复杂,简单来说就是右值,左值都能传过去,即T既能引用左值,又能引用右值

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
// 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
引用折叠以后,统统变成了左值

完美转发: std::forward<T>(t)在传参的过程中保持了t的原生类型属性。

 

 完美转发引用场景

应用在以前写的链表的push_back

main函数 

 

理论而言第一个push_back走左值版本,第二个走右值版本,但是这里都是拷贝构造

 

 这是因为万能引用进行了折叠,这是语法特性,我们进行完美转发

但结果还是不对,这是因为我们给节点没有提供右值引用版本

给节点提供右值引用版本

但结果还是拷贝构造

给insert进行完美转发

给insert相关的都进行完美转发

此时结果正常

移动构造和移动赋值注意事项 

 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任
意一个
(如果实现了这里面的任意一种,编译器会调用拷贝构造)。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类
型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造,
如果实现了就调用移动构造,没有实现就调用拷贝构造。


如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中
的任意一个(如果实现了这里面的任意一种,编译器会调用拷贝赋值),那么编译器会自动生成一个默认移动赋值
。默认生成的移动构造函数,对于内
置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋
值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造
完全类似)


如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。

当存在析构或拷贝构造或构造时,我们可以强制生成移动构造和移动赋值

强制生成默认函数的关键字default:
C++11可以让你更好的控制要使用的默认函数。假设你要使用某个默认的函数,但是因为一些原
因这个函数没有默认生成。比如:我们提供了拷贝构造,就不会生成移动构造了,那么我们可以
使用default关键字显示指定移动构造生成。
 

delete

 禁止生成默认函数的关键字delete:

 如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete即
可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

 这里以不想让Person对象拷贝为例

 

 继承和多态中的final与override关键字前面博客已经说过

将析构用delete修饰,在哪个区域都无法创建对象 ,因为创建的对象最后要调用析构

 

如果要创建对象只有一种方法, 使用new,new出来空间的被指针接收,指针不会调用析构函数

 如果在构造的时候new一块空间,这回导致资源泄露,因为析构被禁了

 此时手动delete会出错,因为要调析构,析构此时调不了

我们可以手动写一个释放空间的函数,调用这个函数即可

 

 这里的空间有俩层,destory只释放了_str所指向的空间,而ptr指向的空间没有被释放

可用这种方法解决

 


 

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

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

相关文章

C#操作字符串方法 [万余字总结 · 详细]

C#操作字符串方法总结C#常用字符串函数大全C#常用字符串操作方法C#操作字符串方法总结C#常用字符串函数大全 Compare 比较字符串的内容&#xff0c;考虑文化背景(场所)&#xff0c;确定某些字符是否相等 CompareOrdinal 与Compare一样&#xff0c;但不考虑文化背景 Format 格…

5.3 BGP路由黑洞

5.2.3实验3:BGP路由黑洞 1. 实验目的 熟悉BGP路由黑洞的应用场景掌握BGP水平分割的配置方法2. 实验拓扑 实验拓扑如图5-3所示: 图5-3:BGP路由黑洞 3. 实验步骤 配置IP地址 R1的配置 <Huawei>syst

前端开发常用案例(一)

前端开发常用案例1.实现三角形百度热榜样式分页效果小米商城自动轮播图效果二级下拉菜单效果时间轴效果展示音乐排行榜效果鼠标移入文字加载动画鼠标悬停缩放效果1.实现三角形 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8…

CCNP350-401学习笔记(51-100题)

51、Which statement about a fabric access point is true?A. It is in local mode and must be connected directly to the fabric edge switch. B. It is in local mode and must be connected directly to the fabric border node C. It is in FlexConnect mode and must …

LVGL开发教程:二、ESP-IDF 使用CmakeList管理自己的文件以及文件夹

本文需要已经安装了Vscode+IDF插件没有安装的请提前安装一下,IDF插件为乐鑫的插件不需要翻墙。需要环境搭建请看下面链接。 环境搭建: VScode+platformIO和Vscode+ESP-IDF两种开发环境搭建 项目例程下载地址: IDF-CmakeTes,密码:8888 另外,由于你和我的路径不一致,下载的工…

富足金字塔:人的努力是为了扩大选择的范围

人的努力是为了扩大选择的范围&#xff0c;这是熵减的另一种表述。富足金字塔代表着人生的三重境界。第一层是温饱。人需要食物、水、住所。第二层是品质。能源、ICT、教育带来更有品质的生活&#xff0c;如智能门锁、智能马桶、扫地机、洗碗机、洗衣烘衣机。第三层是梦想。包括…

netty群聊系统

1设计思路&#xff1a;启动一个服务端&#xff0c;多个客户端第一个客户端启动时&#xff0c;会告诉服务器上线了第二个客户端启动时&#xff0c;告诉服务器上线&#xff0c;并且通知第一个启动的客户端第三个客户端启动时&#xff0c;告诉服务器上线&#xff0c;并且通知第一个…

应用上架小技能:2.1 蓝牙权限使用说明和5.1.1权限使用说明

文章目录 引言I Guideline 2.1 - Information NeededII Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage引言 App是用来蓝牙进行打印小票,需要提供演示视频摄像头、位置和蓝牙的使用场景需要在应用配置文件Info.plist进行说明。uniapp权限说明配置界面 I G…

利尔达在北交所上市:总市值突破29亿元,叶文光为董事长

2月17日&#xff0c;利尔达科技集团股份有限公司&#xff08;下称“利尔达”&#xff0c;BJ:832149&#xff09;在北京证券交易所上市。本次上市&#xff0c;利尔达的发行价格为5.00元/股&#xff0c;发行数量为1980万股&#xff0c;发行市盈率为12.29倍&#xff0c;募资总额为…

2023情人节正经性生活调研报告

省时查报告-专业、及时、全面的行研报告库省时查方案-专业、及时、全面的营销策划方案库【免费下载】2023年1月份热门报告合集ChatGPT的发展历程、原理、技术架构及未来方向2023年&#xff0c;如何科学制定年度规划&#xff1f;《底层逻辑》高清配图今天给大家带来丁香医生最新…

Java Number Math 类,超详细整理,适合新手入门

目录 一、什么是Java Number类&#xff1f; 二、Java Number类提供了哪些基本的数字操作&#xff1f; 三、什么是包装类&#xff1f; 所有的包装类都是抽象类 Number 的子类。 四、什么是Java Math 类 Test类案例&#xff1a;&#xff08;Math.PI 表示一个圆的周长与直径…

代码随想录【Day17】| 513. 找树左下角的值、112. 路径总和、构造二叉树(前+中,中+后)

513. 找树左下角的值 题目链接 题目描述&#xff1a; 给定一个二叉树&#xff0c;在树的最后一行找到最左边的值。 示例 1: 示例2&#xff1a; 难点&#xff1a; 递归法 思路&#xff1a; 这题要找 最底层最左边 很容易就想到层序遍历 递归法的话&#xff0c;有点复杂…

Cosmos NDP编程框架(easyNDP)说明文档

Cosmos NDP编程框架(easyNDP)说明 更新时间&#xff1a;2023-2-17 作者&#xff1a;Gary 一.简介 本文档主要用于说明本简易NDP框架——easyNDP framework的架构、开发新应用以及使用的方法。 在开始前&#xff0c;有一个概念需要提前说明&#xff0c;文档中的块这个概念&…

YOLO-V5 系列算法和代码解析(八)—— 模型移植

文章目录工程目标芯片参数查阅官方文档基本流程Python 版工具链安装RKNPU2的编译以及使用方法移植自己训练的模型工程目标 将自己训练的目标检测模型【YOLO-V5s】移植到瑞芯微【356X】芯片平台&#xff0c;使用C推理&#xff0c;最终得到预期的结果。 芯片参数 芯片参数介绍…

IOS 自动化测试环境搭建

购买MacPDD 比TB JD 便宜500&#xff0c;下单安装homebrew/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"安装npm cnpmbrew install node; npm install -g cnpm --registryhttps://registry.npm.taobao.org;安装类似Andro…

Windows平台使用gdb连接qemu虚拟机上的系统

先安装MinGW&#xff1b; 除了gcc、g&#xff0c;把gdb也选上&#xff1b;可能选第一个就可以了&#xff0c;不清楚把后面几个也选上&#xff1b; 安装完成看一下gcc, g&#xff0c;gdb&#xff0c;编译工具和调试器都有了&#xff1b; 把bin目录加到环境变量&#xff1b; 看一…

element-ui实现动态添加表单项并实现事件触发验证验证

需求分析&#xff1a;点击新增后新增一个月度活动详情&#xff0c;提交时可同时提交多个月度活动详情。点击某一个月度活动信息的删除后可删除对应月度活动信息 H5部分&#xff1a; <el-dialog :title"title" :visible.sync"open" append-to-body>…

数据结构时间空间复杂度笔记

&#x1f57a;作者&#xff1a; 迷茫的启明星 本篇内容&#xff1a;数据结构时间空间复杂度笔记 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;家人们&#xff0c;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤…

基础篇—CSS margin(外边距)解析

什么是CSS margin(外边距)? CSS margin(外边距)属性定义元素周围的空间。 属性描述margin简写属性。在一个声明中设置所有外边距属性。margin-bottom设置元素的下外边距。margin-left设置元素的左外边距。margin-right设置元素的右外边距。margin-top设置元素的上外边距。mar…

Linux 磁盘配额与VDO技术

目录 磁盘容量限额quota技术 磁盘配额分类 对磁盘开启限额服务 xfs_quota管理磁盘配额 edquota 管理磁盘配额 VDO虚拟数据优化 创建VDO卷 vdostats 查看vdo卷的使用情况 磁盘容量限额quota技术 磁盘配额可以限制用户的硬盘可用容量和用户所能创建的最大文件个数 磁盘…