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格式,活动内存碎片整理,内存使 ...
随机推荐
- WCF与Web API在应用上的选择
在最近发布的Visual Studio 2012及.NET 4.5中, 微软正式推出新的网络服务框架ASP.NET Web API.作为ASP.NET MVC 4的一部分,ASP.NET Web ...
- django路由的反向解析
什么是路由的反向解析 我们的路由都是一个匹配关系,对应一个处理的视图函数, 如果我们的匹配关系发生了变化,那么与之对应的访问地址(可能前端直接url链接, 也可能是后端的redrict跳转)都需要跟着 ...
- thinkPHP中session()方法用法详解
本文实例讲述了thinkPHP中session()方法用法.分享给大家供大家参考,具体如下: 系统提供了Session管理和操作的完善支持,全部操作可以通过一个内置的session函数完成. 用法 ? ...
- Python简单实现在线更新下载
Python简单实现 软件在线更新 在线下载(Python simple implementation of software online update and download) 文章来自:htt ...
- 聊Java中的任务调度的实现方法及比较
前言 任务调度是指基于给定时间点,给定时间间隔或者给定执行次数自动执行任务.本文由浅入深介绍四种任务调度的 Java 实现: Timer ScheduledExecutor 开源工具包 Quartz ...
- Python学习日记(四) 集合和元祖
元祖的特性:是一个只读列表.可以循环.可以切片,修改数据遵循'儿子'不能改但'孙子'可能可以改. iterable:可迭代对象(元祖.列表.字串.集合) 元祖宣告方式: tu = (1,2,3,['a ...
- Mybatis,返回Map的时候,将Map内的Key转换为驼峰的命名
每次使用mybatis的时候,简单的连表查询,用Map接收的时候,都是像DB定义的字段一样,类似以下 student_name,student_id,没有转换为驼峰,但是又不能因为这一个定义一个jav ...
- Spring Boot文档
本文来自于springboot官方文档 地址:https://docs.spring.io/spring-boot/docs/current/reference/html/ Spring Boot参考 ...
- Python3执行top指令
import subprocess top_info = subprocess.Popen(["], stdout=subprocess.PIPE) out, err = top_info. ...
- c++第五次作业
运算符重载 一.运算符重载基本规则 1.运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为. 2.一般来讲,重载的功能应当与原有功能相似,不能改变原运算符的操作 ...