C++2.0新特性(五)——<Rvalue_reference和move语义>
一、Rvalue_reference(右值引用)和move语义
1、左右值概念区分
左值:表达式结束后依然存在的对象,我们也叫做变量;
右值:表达式结束后就不存在的临时对象。
2、判断左值和右值
能对表达式取地址的是左值,否则就是右值
左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式)。
3、move语义
右值引用出现再c++03版本之后,它可以避免一些不必要的拷贝和临时对象,当赋值操作的右边是一个右值时,左值可以偷取右值里的资源,而不必去执行allocator(分配内存的动作),这就是move语义。
4、左右值举例分析
- 左右值书写分析

注意:虽然string和复数的举例推翻了左右值书写的准则,但是这是由于一些c++定义类型导致的,我们不要去管他,我们只要记住两点:1、临时对象就是一个右值;2、右值不要出现在等号左边。
5、右值引用
在c++11之前我们对一个函数返回值取地址是错误的,但是在新语法中,我们可以使用&&符号表示对右值取引用或者使用move函数将一个左值变为右值,相应的,我们也要为对应的元素对象实现一个move构造函数或者move赋值函数的重载版本(适用容器中操作元素时)。比如在做容器的在c++ 2.0之后,容器的插入动作都提供了一个insert的重载版本,专门适用这种新语法,如下所示:

当编译器检测到我们insert的值是一个右值(move函数返回一个右值)或者右值引用(&&,临时对象都会被当成右值引用)时,会调用下面新增的这个重载函数,让它偷取这个右值的东西免去自身取构造内存的动作,因为插入动作会调用拷贝构造函数,如果插入的元素是一个基本类型而不需要额外提供什么,但是如果插入的是一个复杂类型,原本我们需要写一个拷贝构造函数,开辟一块内存一个个的赋值过去,但现在我们要提供一个move搬移构造就行了(比如像string(编译器已经实现)类,move构造函数只是将既有的内部字符数组赋予新对象就行了,此时相当于新对象指针和原对象指针指向同一个地方,要注意执行move后原对象的指针是个不确定状态,不能使用),所以任何非平凡的类(除了基本类型),都应该提供move构造和move assignment(赋值)函数:


- 这里说一下move中的偷的概念,所谓偷就是借用之前的值,对于指针来说就是两个指针指向同一个地方,也就是说move语义就是指针的浅拷贝,为了指针的安全我们还要在偷完之后将原来的指针打断以禁止后续再使用这个值;
- 右值经函数转交到下一个函数时会变成一个左值。

6、右值引用使用准则:
使用右值的函数也不能返回局部变量


7、move类举例
- move构造函数对接的是拷贝构造函数,下面将两个做对比,move做浅拷贝后,要将原来指针赋空(记住一定要将原来的指针赋空打断,因为容器在做插入操作时产生的临时对象生命周期结束后会调用析构函数释放指针内存,如果原来的指针没有赋空析构后容器里面已插入的指针就是悬空指针,引起崩溃,而前面指针赋空断开则不会有影响(对一个空指针delete操作相当于什么都不做))

- 拷贝赋值对接move拷贝赋值函数

8、有无move版本对容器的影响
- Vector 插入元素时影响很大
- 除vector以外的其他容器插入元素时影响都不大
- deque的极端情况,比如每次都在buffer中间插入,会产生很多的拷贝动作,影响也大
C++2.0新特性(五)——<Rvalue_reference和move语义>的更多相关文章
- [转]Servlet 3.0 新特性详解
原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...
- iOS开发——新特性OC篇&Swift 2.0新特性
Swift 2.0新特性 转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度 ...
- [C#]6.0新特性浅谈
原文:[C#]6.0新特性浅谈 C#6.0出来也有很长一段时间了,虽然新的特性和语法趋于稳定,但是对于大多数程序猿来说,想在工作中用上C#6.0估计还得等上不短的一段时间.所以现在再来聊一聊新版本带来 ...
- webpack 4.0.0-beta.0 新特性介绍
webpack 可以看做是模块打包机.它做的事情是:分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式 ...
- Day07 jdk5.0新特性&Junit&反射
day07总结 今日内容 MyEclipse安装与使用 JUnit使用 泛型 1.5新特性 自动装箱拆箱 增强for 静态导入 可变参数方法 枚举 反射 MyEclipse安装与使用(yes) 安装M ...
- 四、C# 5.0 新特性——Async和Await使异步编程更简单
一.引言 .NET 4.5 的推出,对于C#又有了新特性的增加--就是C#5.0中async和await两个关键字,这两个关键字简化了异步编程,之所以简化了,还是因为编译器给我们做了更多的工作,下面就 ...
- [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐
[翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...
- android6.0、7.0、8.0新特性总结之开发应用时加以考虑的一些主要变更。
android6.0 参考一:简书Android 6.0 新特性详解 参考二:关于Android6.0以上系统的权限问题 参考三:值得你关注的Android6.0上的重要变化(一) 参考四:值得你关注 ...
- Redis4.0新特性
redis 4.0 新特性 Redis 4.0在2017年7月发布为GA.包含几个重大改进:更好的复制(PSYNC2),线程DEL / FLUSH,混合RDB + AOF格式,活动内存碎片整理,内存使 ...
随机推荐
- MVC4 部署 could not load file or assembly system.web.http.webhost 或是其它文件出误
自从VS2010发布之后使用它来做开发的程序员越来越多,其中很多人使用了MVC来作为新的开发框架,但是在系统部署的时候我们也遇到诸多问题,因为目前大多数windows服务器采用的还是Windows S ...
- NEST search查询
/// <summary> /// GET /megacorp/employee/_search /// </summary> /// <returns></ ...
- 查询本地ip以及ip地址库查询
四种方法查询本地ip from urllib2 import urlopen from json import load my_ip = urlopen('http://ip.42.pl/raw'). ...
- rabbitmq实战:一、天降奇兵
缘由,最近换了工作,而新的项目中使用了celery+rabbitmq来实现一个分布式任务队列系统,为了能够维护好这套系统,只能来学习一下这两个组件,顺便把学习笔记记录下来,留作以后回顾,当然如果碰巧能 ...
- 尚硅谷韩顺平Linux教程学习笔记
目录 尚硅谷韩顺平Linux教程学习笔记 写在前面 虚拟机 Linux目录结构 远程登录Linux系统 vi和vim编辑器 关机.重启和用户登录注销 用户管理 实用指令 组管理和权限管理 定时任务调度 ...
- C#中hashtable如何嵌套遍历
嵌套hashtable的遍历取值怎么做 hastable中嵌套了hashtable,想用递归的方式把所有hashtable中的key和value取出来 foreach (DictionaryEntry ...
- (备忘)cron表达式的用法
一.结构 cron表达式用于配置cronTrigger的实例,实现任务调度的功能. Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义,Cron有如下两种语法格 ...
- requests-html模块(下)
render方法 我们先理一下关系requests和的作者是同一个人,pyppeteer是nodejs中puppeteer的非官方实现 requests-html调用的pyppeteer与浏览器进行交 ...
- Linux下 启动tomcat 时候同时日志命令
./startup.sh && tail -f ../logs/catalina.out
- C++(三十九) — 主函数中增加调试信息
程序调试技术: (1)阅读程序,静态代码复查: (2)“cout大法” (3)使用开发工具,断点 int main() { TShape s(lu, lu); cout << __ ...