C++11(二)右值引用移动语义

news2024/12/22 23:27:04

🧸🧸🧸各位大佬大家好,我是猪皮兄弟🧸🧸🧸
在这里插入图片描述

文章目录

  • 左值引用和右值引用
    • 1.左值与左值引用
    • 2.右值与右值引用
    • 3.左值引用和右值引用比较
      • 左值引用引用右值
      • 右值引用引用左值
    • 4.右值引用之后的变化
    • 5.左值引用使用问题
    • 6.移动构造
    • 7.移动赋值
    • 8.STL变化
    • 9.完美转发
    • 10.默认移动构造和移动赋值
      • 编译器默认生成移动构造和移动赋值的条件

左值引用和右值引用

之前学过的引用几乎都是左值引用,但是无论是左值引用还是右值引用,都是给对象取别名

1.左值与左值引用

左值可以是变量或者表达式,左值引用的真正特点就是能够去取它的地址,本来也应该算上可以赋值这个特点,但是const修饰的左值不可以,所以可以取地址的就是左值

那么左值引用就是对左值取别名

int a;//左值
int &b=a;//左值引用

左值既可以出现在等号左边也可以出现在赋值符号右边

2.右值与右值引用

右值也是一个变量或者表达式,右值引用只能出现在赋值符号右边,因为它不能够被取地址,所以无法被赋值。右值一般就是字面量和表达式返回值的临时对象

double x=1.1,y=2.2;
//以下的都是右值
10;
x+y;//字面量
fmin(x,y);//返回值的临时对象

右值引用:对右值取别名,右值引用是两个&&

double x=1.1,y=2.2;
//以下的都是右值
10;
x+y;//字面量
fmin(x,y);//返回值的临时对象

//右值引用
int&& rr1=10;
double&& rr2 = x+y;
double&& rr3 = fmin(x+y);

3.左值引用和右值引用比较

左值引用引用右值

一般左值引用是不能给右值引用取别名的,因为左值引用的表达式需要可以取地址和赋值

double&l = x+y/*右值*/;//报错

但是,const左值引用是可以引用右值的

const double&r = x+y;//编译通过

因为C++11之前,没有右值引用,那怎么办呢?所以就用const左值引用的方式来引用右值,所以也推荐拷贝构造和赋值运算符重载写成const左值引用,因为不仅仅可以解决权限扩大缩小的问题,而且可以通过const左值引用来引用右值。

右值引用引用左值

普通的右值引用也是不能引用左值的

int c =10;
int && r = c;//报错

但是,可以用move来让编译器把左值识别成右值

int c=10;
int &&r = move(c);
//这样就可以了

4.右值引用之后的变化

右值是不能够取地址的,但是给右值被右值引用了之后,会导致右值被存储到特定位置,且可以取到该位置的地址。也就是说:

10;
double x=1.1,y=2.2;
int&rr1=10;
const double && rr2=x+y;

上面的rr1和rr2都是左值,这也会牵扯到完美转发的问题

5.左值引用使用问题

左值引用解决问题:
①做参数:a.减少拷贝,提高效率 b.做输出型参数
②做返回值:a.减少拷贝,提高效率 b.引用返回可以修改返回对象(比如map的operator[],修改Value)

左值引用的问题:在函数类创建的临时对象需要返回,那只能传值返回,就做不到减少拷贝,提高效率。所以有些场景是左值引用做不到的

如果说要求vector<vector<int> generate(int numRows){}>这里需要减少拷贝,怎么做?
①全局vector,但是全局变量会有线程安全问题,不安全
②new 返回vector<vector>的指针,但是忘记释放就会内存泄漏,或者用RAII的思想来搞
③输出型参数 void generate(int numRows,vector<vector<int>>&vv);
④利用移动构造(下面讲)

6.移动构造

C++把右值分为了两种
1.内置类型的右值 – 纯右值
2.自定义类型的右值 – 将亡值(通常都是一些临时对象,生命周期就在这一行)

//拷贝构造
string(const string& s)
	:_str(nullptr);
{
	string tmp(s);
	swap(tmp);
}
//移动构造
string(string&&s)//因为s不可取地址,不可赋值,所以不加const
	:_str(nullptr)
{
	swap(s);//因为s是右值,将亡,所以直接交换
}

因为有资源的转移,所以叫移动构造


string str1(move(str1));
string str2(string("hello"));

移动构造比拷贝构造的代价小太多,拷贝构造需要先构造一个临时变量(而这个构造是深拷贝,当然也可以用引用计数和写时拷贝来进行优化),然后将这个临时变量再拷贝构造给原来的变量。而移动构造在函数内部就资源转移了,只是交换了一下管理的指针。

编译器也是很聪明的,有const左值引用的拷贝构造和右值引用的移动构造,都可以引用右值,但是确是调用的移动构造,因为它能够识别到这是一个将亡值。挑选最匹配的去调用

7.移动赋值

string ret;
ret = to_string(1234);
//这时候就需要移动赋值
//拷贝赋值
string& operator=(const string&s)
{
    string(tmp);
    swap(tmp);
    return *this;
}

//移动赋值
string& operator=(string&&s)//构造
    swap(s);//s将亡
    return *this;
}

8.STL变化

C++11以后,STL就提供了移动构造和移动赋值
右值引用除了移动构造和移动赋值以外,insert也用到了
在这里插入图片描述
还有就是增加了emplace
在这里插入图片描述
传递多个左值/右值(因为会引发万能引用/引用折叠)来进行插入

9.完美转发

先来看一个现象
在这里插入图片描述
右值引用&&和模板在一起,就会引发一个东西叫做 万能引用/引用折叠
引用折叠的意思就是传左值过去的时候,会把&&折叠成&,以对左值进行兼容(有了引用折叠,其实就可以替代单纯的左值引用,但是为了向前兼容,左值引用还存在)

然后再上面也说过,右值引用会把右值存在一个特定的位置,导致右值的别名是一个左值(因为可以对这个别名取地址)
所以上面就可以看到都是左值引用的结果

C++11中就提供了一个东西—>完美转发
在这里插入图片描述
可以让别名t保持它原有的属性,就可以做到去调用右值引用
完美转发的意思就是你把我给你的东西原封不动的交给别人,不要改变它的属性

在一个调用链中连续调用就会用到,比如说list的push_back

void push_back(const T& x)
{
	//    ...    
}
void push_back(T&&x)//引用折叠,既可引用左值也可引用右值
{
    
}

push_back调用的是insert,如果不进行完美转发,那么push_back传给insert的就是左值,然后就又会去调用拷贝构造,并不会调用移动构造,效率也不会得到提升,在整个调用链上都需要完美转发一下

10.默认移动构造和移动赋值

我们以前知道的默认成员函数有六种:①构造函数 ②拷贝构造函数 ③赋值运算符重载函数 ④析构函数 ⑤取地址运算符重载函数 ⑥const取地址运算符重载函数

C++11之后,新增添了两个 ①移动构造 ②移动赋值

编译器默认生成移动构造和移动赋值的条件

①如果没有实现移动构造函数,且没有自己实现析构函数,拷贝构造,拷贝赋值重载的任意一个(三个都不写才会生成,但是这三个只要有一个写了,基本都要写),那么编译器才会自动生成,并且,默认移动构造对于内置类型对象进行值拷贝,自定义类型对象,则看这个对象是否实现移动构造,如果实现就调用它的移动构造,没有实现就调用拷贝构造。
②移动赋值同理

在这里插入图片描述

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

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

相关文章

运动的人需要什么装备?运动健身装备推荐分享

平时健身运动得比较多&#xff0c;对这些健身运动装备也有一定的了解。看今天有点时间&#xff0c;就在这里给大家说说我平时在用的健身装备好了&#xff0c;既可以当成是我自己这些时间健身运动的阶段性总结&#xff0c;也看看能不能对大家有些帮助。不多说别的&#xff0c;直…

【Mybatis编程:查询相册数据列表】

目录 1. 书写执行的SQL语句 2. 在项目的根包下创建pojo.vo.AlbumListItemVO类 3. 在AlbumMapper.java中添加抽象方法 4. 在AlbumMapper.xml中配置SQL语句 5. 在AlbumMapperTests.java中编写并执行测试 1. 书写执行的SQL语句 需要执行的SQL语句大致是&#xff1a; SELECT …

AnalysisView

元数据分析&#xff1a;血统分析、血液分析

[Power BI] 认识Power Query和M语言

数据清洗&#xff0c;可理解为数据整理&#xff0c;对从各类数据源导入的数据&#xff0c;通过一定的方法(如数据的增删改、转换、逆透视、合并等)进行处理&#xff0c;整理成符合要求的数据&#xff0c;然后加载到数据模型中&#xff0c;进行数据可视化 在Power BI中&#xf…

【Java八股文总结】之面试题(三)

文章目录面试线程相关1、线程有哪些状态?2、线程池的核心参数3、sleep VS wait4、lack VS synchronized5、volatile能否保证线程安全?6、悲观锁VS乐观锁7、HashTable Vs CurrentHashMap8、ThreadLocal的理解虚拟机相关1、JVM 内存结构1、程序计数器&#xff08;线程私有&…

Linux安装CUDA 添加环境变量 多版本CUDA切换 (软链接)

一、 Linux安装CUDA 步骤1. 去官网找到你想安装的CUDA版本&#xff1a; CUDA Toolkit Archive | NVIDIA Developer 步骤 2. 根据你的系统选择合适的系统版本 其中注意上图标红框的 Distribution 和Version 可用指令 cat /proc/version查看&#xff0c;如下&#xff1a; 选择…

居舍杂志居舍杂志社居舍编辑部2022年第27期目录

行业聚焦《居舍》投稿&#xff1a;cnqikantg126.com 走进企业|共推区域合作交流 共助行业转型升级——走进广州百利文仪北京分公司 1-2 CIFF|办好家居产业的连锁展会平台&#xff0c;助推家居产业高质量发展 3-5 CIFF上海虹桥|观展必看&#xff1a;这份史上最全品牌…

【CNN】搭建AlexNet网络——并处理自定义的数据集(猫狗分类)

前言 2012年&#xff0c;AlexNet横空出世。它首次证明了学习到的特征可以超越手工设计的特征。它一举打破了计算机视觉研究的现状。 AlexNet使用了8层卷积神经网络&#xff0c;并以很大的优势赢得了2012年ImageNet图像识别挑战赛。 论文地址&#xff1a;http://papers.nips.c…

Windows OpenGL ES 图像色彩替换

目录 一.OpenGL ES 图像色彩替换 1.原始图片2.效果演示 二.OpenGL ES 图像色彩替换源码下载三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 特效 零基础 …

MongoDB的使用

MongoDB 是一个跨平台的&#xff0c;以 JSON 为数据模型的文档数据库&#xff0c;是当前 NoSQL 数据库产品中最热门的一种。它介于关系数据库和非关系数据库之间&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的产品。 1、 MongoDB 与 MySQL 数据库 数据…

openGauss 高效数据压缩算法

openGauss 高效数据压缩算法 2.1 主要创新技术点 openGauss 的主要创新技术点总结如下&#xff1a; &#xff08;一&#xff09;改进压缩算法&#xff0c;压缩数据单位依然是选择页级别&#xff0c;进一步结合 Page 结构以及本身数据的特征&#xff0c;将 page 交给通用压缩算…

使用ClickHouse JDBC官方驱动,踩坑无数

前言 最近遇到一个ClickHouse的线上问题&#xff1a; Code: 242, e.displayText() DB::Exception: Table is in readonly mode(zookeeper path:/clickhouse/tables/02/xxx) (version 21.12.4.1) (official build) 这个问题我在网上查原因说是由于Zookeeper压力过大&#xf…

MySQL基础篇之多表查询(内连接、外连接、自连接、子查询、union)

05、多表查询 5.1、多表关系 1、概述 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分…

maven学完总结!少走弯路一百遍

一、学习方式 学完maven大概花了两天的时间&#xff0c;其实之前学javaweb时用的是maven&#xff0c;因此有点接触&#xff0c;一到两天便能学完maven。 这次我也做了每个知识点的流程图。 但是我学完之后我发现可能没什么要做流程图的&#xff0c;因为更多的是自己动手操作的…

澳大利亚昆士兰大学博士后职位—生物活性肽

【国外博士后招聘-知识人网】澳大利亚昆士兰大学博士后职位—生物活性肽 昆士兰大学&#xff08;The University of Queensland&#xff09;&#xff0c;简称“昆大”“UQ” &#xff0c;世界高等科研学府。始建于1910年&#xff0c;是昆士兰州第一所综合型大学&#xff0c;同时…

网页JS自动化脚本(二)查找定位页面元素的方法

我们写脚本往往是要提取某些关键字,那么我们对于元素的查找和定位就很重要首先我们打开浏览器,鼠标右键点击我们想要定位的元素,然后点击审查元素 然后浏览器会弹出调试工具台,我们继续看下图右侧的调试工具台 可以看到我画了9个序号,可以看到从第1个到第7个全部是div容器元素,…

[附源码]Python计算机毕业设计Django+Vue的健身房会员系统的设计与实现

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

数字信号处理-11-FPGA FFT IP应用实例

前言 本文根据FFT相关原理进行设计构建工程&#xff0c;仿造前文的工程构建的混频功能的工程&#xff0c;设计工程显示该混频信号的功率谱&#xff0c;然后进行仿真分析。 FFT仿真与分析 本文不再针对FFT的原理进行过多赘述&#xff0c;提供一份简单的matlab仿真代码。根据仿…

在Soliworks中便捷添加自己的LOGO

在Soliworks中&#xff0c;一般采用草图图片样条曲线的方式绘制个人logo&#xff0c;但是对于一些复杂的logo&#xff0c;对每个模型都绘制一遍显然是不显示的&#xff0c;所以我摸索了一套只需绘制LOGO一遍&#xff0c;就能够将其应用在其他模型的方式。 1. 绘制LOGO 采用草…

黑马点评--好友关注

好友关注&#xff1a; 关注和取关 在探店图文的详情页面中&#xff0c;可以关注发布笔记的作者&#xff1a; 需求&#xff1a;基于该数据结构&#xff0c;实现两个接口 关注和取关接口 Overridepublic Result follow(Long id, Boolean isFollow) {// 1.获取登录用户Long us…