C++11右值引用

什么是左值,什么是右值?

不可以单纯字面去理解,等号左边是左值,等号右边是右值。
左值:可以修改的可以认为是左值,左值通常是变量
右值:通常是常量,表达式或函数返回值(临时对象)

int main()
{//左值引用的定义int a = 0;int& b = a;//右值引用的定义int x = 1,y = 2;int&& c = 10;int&& d = x+y;//左值引用不能引用右值,const左值引用可以const int &e = 1;//右值引用不能引用左值,需要将左值move成右值才可以int&& c = move(a);
}

c++11将右值区分为:纯右值和将亡值
纯右值:基本类型的常量或者临时对象
将亡值:自定义类型的临时对象

纯右值我们上面已经介绍了,下面我们来介绍一下将亡值:

class String
{
public:String(const char* str = "")//默认构造{_str = new char[strlen(str)+1];strcpy(_str,str);}String(const String& s)//拷贝构造{cont<<"String(const String& s)深拷贝"<<endl;_str = new char[strlen(s._str)+1];strcpy(_str,s._str);}String& operator=(const String& s)//=重载{cout << "String& operator=(const String& s)深拷贝" << endl;if (this != &s){char* newstr = new char[strlen(s._str) + 1];strcpy(newstr, s._str);delete[] _str;_str = newstr;}return *this;}~String(){delete[] _str;}
private:char* _str;
};

**

右值的意义:

**
这是我们认识右值引用前简单模拟的string类。左值引用帮我们减少了拷贝。但是他有一些缺陷:
如果传过来的引用是一个将亡值,也就是马上就要亡的值(等出了这个作用域,他可能也不用了,就析构了),那我们还拷贝他的内容,多浪费啊,直接一个swap,交换一下地址,把他的值拿过来用,这样就不用拷贝了,提高了效率。而且也是将亡值了会自己析构,还省去了我们析构的事情。
但是!我们如何区分传过来的值是不是将亡值?
那么右值引用就帮我们解决了这个问题。

拷贝构造:

String(const String& s)
{cont<<"String(const String& s)深拷贝"<<endl;_str = new char[strlen(s._str)+1];strcpy(_str,s._str);
}
String(String&& s):_str(nullptr)
{cont<<"String(String&& s)移动拷贝"<<endl;swap(_str,s._str);
}

operator=

String& operator=(const String& s)
{cout << "String& operator=(const String& s)深拷贝" << endl;if (this != &s){char* newstr = new char[strlen(s._str) + 1];strcpy(newstr, s._str);delete[] _str;_str = newstr;}return *this;
}
String& operator=(const String&& s)
{cout << "String& operator=(const String&& s)移动赋值-效率高" << endl;swap(_str, s._str);return *this;
}

右值引用本身没有太多意义,右值引用实现了移动构造和移动赋值
那么面对接受函数传值返回对象(右值)等场景,可以提高效率

总结:

右值引用做参数和做返回值减少拷贝的本质是利用了移动构造和移动赋值
左值引用和右值引用本质的作用都是减少拷贝,右值引用本质可以认为是在弥补左值引用不足的地方,他们俩相辅相成

c++98
左值引用:解决的是传参过程中的返回值过程中的拷贝
做参数:void f1(T x)->void f1(const T& x) 传参过程中减少拷贝
做返回值:T f2()->T& f2() 解决返回值过程中的拷贝
但是要注意这里有限制,如果返回对象出了作用域不在了就不能传引用,这个左值引用无法解决,等待c++11右值引用解决

c++11
右值引用:解决的是传参后,push/insert函数内部将对象移动到容器空间上的问题+传值返回接受 返回值的拷贝
做参数:void push(T&& x) 解决push内部不在使用拷贝构造x到容器空间上而是移动构造过去
做返回值:T f2() 解决的外面调用接受f2()返回对象的拷贝,T ret = f2()
这里就是右值引动的移动构造,减少了拷贝

解决右值属性丢失问题:完美转发

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力,
// 但是引用类型的唯一作用就是限制了接收的类型,后续使用中都退化成了左值,
// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
template<typename T>
void PerfectForward(T&& t)
{Fun(t);//右值引用会在第二次之后的参数传递过程中右值属性丢失,下一层调用会全部识别为左值//完美转发解决
}
int main()
{PerfectForward(10);// 右值int a;PerfectForward(a); // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b);// const 左值PerfectForward(std::move(b)); // const 右值return 0;
}

运行后发现所有右值经过第二次传递后右值属性丢失,下一层全部识别为左值
在这里插入图片描述

void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
// std::forward<T>(t)在传参的过程中保持了t的原生类型属性。
template<typename T>
void PerfectForward(T&& t)
{Fun(std::forward<T>(t));
}
int main()
{PerfectForward(10);// 右值int a;PerfectForward(a);// 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b); // const 左值PerfectForward(std::move(b)); // const 右值return 0;}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈C/C++指针和引用在Linux和Windows不同环境下的编码风格

目录 0. 前言 1. 代码块、函数体上的 { } 的规范 2. 指针和引用中的 * 和 & 符号的位置 1. Linux 环境下编码风格(gcc) 2. Windows 环境下编码风格(Visual Studio) 3. 简单总结 0. 前言 C/C因为高度的自由性&#xff0c;并没有对一些常见的编码风格进行限制&#…

Hive3:数据的加载与导出

一、加载数据 在创建表之后&#xff0c;表中没有数据&#xff0c;我们不可能insert存入数据。 而是&#xff0c;通过数据加载&#xff0c;将HDFS中的数据关联到Hive表中。 建表 CREATE TABLE myhive.test_load(dt string comment 时间&#xff08;时分秒&#xff09;, user_…

某客户ODS数据库undo段问题分析处理

概述 ODS数据库在7月22日4个时间点02:03,05:17,07:04,08:53分别报如下错误&#xff1a; 原因分析 Ora-1628&#xff1a;max # extents 32765 reached for rollback segment _SYSSMU19990_761259507$ Oracle 官方解释&#xff1a; Cause: An attempt was made to extend a roll…

VScode:前端项目中导出和导入插件

# 终端运行&#xff1a;导出扩展插件到指定路径&#xff08;txt&#xff09; code --list-extensions > C:\Users\UserName\Documents\extensions.txt # 终端运行&#xff1a;导入指定路径&#xff08;txt&#xff09;的扩展插件 Get-Content C:\Users\UserName\Documen…

渗透测试实战-菠菜站渗透测试(Nacos反序列化漏洞利用)

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…

Python 设计模式之工厂函数模式

文章目录 案例基本案例逐渐复杂的案例 问题回顾什么是工厂模式&#xff1f;为什么会用到工厂函数模式&#xff1f;工厂函数模式和抽象工厂模式有什么关系&#xff1f; 工厂函数模式是一种创建型设计模式&#xff0c;抛出问题&#xff1a; 什么是工厂函数模式&#xff1f;为什么…

uniapp版本更新除了plus.runtime.getProperty的解决办法

以下是展示图 带尺寸的图片: 首先把以下代码放到想要更新弹出的页面 //template部分<uni-popup ref"popup" background-color"#fff"><versionUp handleCloseVersion"closeVersion"></versionUp></uni-popup>//script…

应急响应:Windows 入侵排查思路.

什么是应急响应. 一个组织为了 应对 各种网络安全意外事件的发生 所做的准备 以及在 事件发生后 所采取的措施 。说白了就是别人攻击你了&#xff0c;你怎么把这个攻击还原&#xff0c;看看别人是怎么攻击的&#xff0c;然后你如何去处理&#xff0c;这就是应急响应。 目录&am…

上海电信万兆宽带2026年将实现全城覆盖

为了响应号召&#xff0c;上海力争到2026年&#xff0c;初步建成以5G-A和万兆光网为标志的全球双万兆城市。上海电信正式对外宣布将于8月30日正式上线“美好家万兆融合套餐”&#xff0c;同时发布速率行业领先的“5G-A套餐”&#xff0c;上线“随翼选”云翼智选礼包&#xff0c…

【Go】手写简易go webserver

核心&#xff1a;实现net/http库中handler接口的ServeHTTP方法的实例&#xff0c;通过http.ListenAndServe注册后&#xff0c;所有的请求都会打到该实例的ServeHTTP方法里。Context是对请求对象和响应对象的封装&#xff0c;实现了获取请问请求参数、设置状态码、设置响应头、设…

WINDOWS核心编程-----3章,内核对象,是现在不同账号下测试

系列文章目录 终端服务命名空间中内核对象的测试程序 TerminalService程序需要用登录不同的windows账号同时运行。才能看出效果 建议测试流程 1&#xff0c;先登录windows账号A&#xff0c;运行两个本程序实例 2&#xff0c;保持上述两个实例人在运行中&#xff0c;在登陆wind…

Vue3 搭建前端工程,并使用idea配置项目启动

1 下载node.js 先下载 node.js LTS 并安装&#xff1a;node.js 的 npm&#xff0c;用于管理前端项目包依赖&#xff0c;这里以 14.17.3 这个版本为例。如果已经安装过 node.js&#xff0c;可以在设置中找到应用&#xff0c;点进去搜索 node.js 即可卸载 node.js 14.17.3 安装…

C语言典型例题32

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.9 编程序用getchar函数读入两个字符给c1&#xff0c;c2&#xff0c;然后分别用putchar函数和printf函数输出这两个字符。 &#xff08;1&#xff09;变量c1&#xff0c;c2应该定义为字符型或者整型吗&#x…

Flutter 学习之旅

本文只针对个人学习所遇问题&#xff0c;以及解决方案进行记录&#xff0c;不深刨原理。 不深刨原理是因为我也才开始学习&#xff0c;讲不明白&#xff0c;有可能还误导大家 &#xff0c;希望多多包涵。 问题一&#xff1a; 如何通过appBar去设置状态栏字体颜色以及状态栏透…

LLM - 使用 HuggingFace + Ollama 部署最新大模型 (GGUF 格式 与 Llama 3.1)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/141028040 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Ollama…

【Linux】Ubuntu20.04系统中能在命令行ping通百度等网站,而在浏览器中不能上网的问题解决方法

今天离开学校&#xff0c;在家中打开ubuntu系统准备上网&#xff0c;发现浏览器打不开&#xff0c;但是QQ是可以发消息的&#xff0c;证明WIFI应该是没有问题的&#xff0c;但是谷歌和火狐浏览器就是打不开网址&#xff0c;很奇怪&#xff01; 先检查我们Linux能不能ping通 开一…

基于Jakarta,TypeScript,Golong的国密SM2、3、4

文章目录 前言一. Jakarta代码二. TypeScript三.golang 前言 最近还要深度研究hutools底层实现&#xff0c;一定要搞透澈&#xff0c;本章将会是持续更新 所有密钥由Jakarta统一生成&#xff0c;因为没测试其他语言生成是否可以 参考资料&#xff1a; Java代码实现SM2算法以及…

整理 钢琴 基础知识

大普表和钢琴键盘对照表 一 大普表和钢琴键盘对照表 二 五线谱、键位、左右手 八分音符 坐姿 手型

机器学习——支持向量机(SVM)(1)

目录 一、认识SVM 1. 基本介绍 2. 支持向量机分类器目标 二、线性SVM分类原理&#xff08;求解损失&#xff09; 三、重要参数 1. kernel&#xff08;核函数&#xff09; 2 .C&#xff08;硬间隔与软间隔&#xff09; 四、sklearn中的支持向量机&#xff08;自查&#…

使用Adobe Photoshop CS5给图片加水印

使用Adobe Photoshop CS5给图片加水印 前言1.我这里使用的是Adobe Photoshop CS52.新建空白画布3.写入水印内容4.按 Ctrl T 将其倾斜5.右键图层选择“混合选项”6.选择描边&#xff0c;颜色选择灰色7.效果如下8.填充选择0&#xff0c;不透明度选择75%9.打开编辑&#xff0c;选…