C++11--右值引用

1.引用

右值引用是在C++11中所引进的,在前面,我们已经了解并使用过了引用,引用的作用就是给某一个变量取别名,但实际上,我们使用的引用是左值引用,而我们现在要了解的是与左值引用相对应的右值引用。

无论左值引用还是右值引用,都是给对象取别名。为了更好的区别和了解左值引用和右值引用,我们需要理解两种引用的使用与区别。

2.左值引用和右值引用

2.1左值引用

左值是一个表示数据的表达式(如变量名或解引用的指针),通常可以修改的变量我们都称之为左值,我们可以获取它的地址+可以对它赋值

左值引用通常是给左值的引用,给左值取别名。

正如赋值符号 = 的左边是被赋值改变的变量,而左值可以出现赋值符号的左边,但右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。

 2.2右值引用

右值也是一个表示数据的表达式,但与左值相对,右值一般是不可修改的常量或者不等式、函数返回值等临时对象。如:基本类型的常量、表达式返回值,函数返回值等等。

右值引用通常是对右值的引用,给右值取别名。

相比于左值,右值可以出现在赋值符号 = 的右边,但是不能出现出现在赋值符号的左边,右值不能取地址

2.3左值引用和右值引用的使用

2.31左值引用的使用

左值引用的使用格式是给对应左值取别名前加上一个&符号,前面我们也已经学过。

格式:左值变量类型 & 别名名称  =  左值

需要注意的是,左值引用一般情况下大多数都是给左值取别名,但是也可以给右值取别名。例如使用const修饰别名类型,使得其具有常性,不可被修改,达到给右值取别名的效果。

2.32右值引用的使用 

相比于左值引用的使用,右值引用的使用是在别名前加两个 & 符号,也就是 && ,再给对应的右值取别名。

格式:右值变量类型 && 别名名称  =  右值

同样的,右值引用正常情况大对数都是用于对右值取别名,但通过特殊手段,使用 move()也是可以给左值取别名的。

2.4左值引用与右值引用的比较

左值引用:

  • 一般只能引用左值,不能直接引用右值
  • const 左值引用可以将别名变得具有常性,使得const左值引用可以给右值取别名。
  • 左值:通常可以修改的变量我们都称之为左值。

右值引用:

  • 一般只能引用右值,不能直接引用左值
  • 通过move左值改变值的属性,右值引用可以给左值取别名。
  • 右值:一般是不可修改的常量或者不等式、函数返回值等临时对象。

3.引用的使用场景

了解了左右值引用如何使用后,我们需要知道左右值两种引用具体是使用在哪些地方,有各自具有怎样的优势。

3.1左值引用

左值引用的主要作用实则是比较好知道的。

对于左值引用的参数与函数返回值,其传递的效率都是十分高的,这是左值引用使用的场景。这点可以与指针想比较,两者是相似的。

左值引用的取的别名就相当于变量本身,可以直接通过对别名的修改直接影响引用左值本身,尤其是其作为函数返回值与参数,不需要拷贝临时对象,这是十分高效的。而左值引用作在类中的成员函数作为函数参数与返回值是十分常见的。

不足之处:

对于函数体中产生的临时对象,其不能直接使用左值引用去作为返回值。这是因为函数体内产生的临时对象出了函数本身作用域将会被销毁,但是如果其作为左值引用为返回值,其得到的返回值的空间将是已经被销毁的空间,将会产生难以预料的错误。

3.2右值引用

对于左值引用的不足之处,右值引用的出现很好的解决了其缺点。

在类的中,有资源开销的对象,其拷贝构造与赋值重载的使用通常是需要进行深拷贝的,而对于临时变量而言,对其使用深度拷贝实际上是十分浪费效率的,临时变量中存储的内存资源是使用完后即将要销毁的,这并不能很好的利用临时对象的资源。而右值引用的出现解决则很好的解决了临时对象资源利用的问题。

3.21移动拷贝和移动赋值

移动拷贝和移动赋值是右值引用出现的主要原因,他解决了类中对临时对象空间资源的利用。

右值实际上分成纯右值和将亡值。纯右值是基本类型的常量或临时对象,而将亡值是自定义类型的临时对象,使用过后将会自动被析构销毁掉。

class String
{
private:char* _str;
public:String(const char* str = ""){_str = new char[strlen(str) + 1];//多开辟一个字节空间存放'\0'//strcpy(_str, str);for (int i = 0; i <= strlen(str); ++i){_str[i] = str[i];}}void swap(String& s){::swap(_str, s._str);}// 拷贝构造String(const String& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl; \_str = new char[strlen(s._str) + 1];for (int i = 0; i <= strlen(s._str); ++i){_str[i] = s._str[i];}}// 赋值重载String& operator=(const String& s){cout << "string& operator=(string s) -- 深拷贝赋值" << endl;_str = new char[strlen(s._str) + 1];for (int i = 0; i <= strlen(s._str); ++i){_str[i] = s._str[i];}return *this;}// 移动构造String(String&& s):_str(nullptr){cout << "string(string&& s) -- 移动构造" << endl;swap(s);//交换临时的将亡值对象的资源}// 移动赋值String& operator=(String&& s){cout << "string& operator=(string&& s) -- 移动赋值" << endl;swap(s);//交换临时的将亡值对象的资源return *this;}~String(){delete[] _str;_str = nullptr;}void Print(){cout << _str << endl;}
};
String func(const char* str)
{String temp(str);return temp;//返回的是temp的临时拷贝对象--将亡值
}

移动拷贝和移动赋值的本质是:将传递的临时对象参数的资源窃取交换变为自己的,通过这种方式,可以在极其高效的前提下达到深拷贝的效果。其中在STL的一些容器中也加入了移动拷贝和移动赋值的接口函数,如list、vector等容器都有。

3.3模版中的万能引用&&

在模板中,可以使用带右值引用相同的引用符号&&来表示万能引用。

需要注意的是在模板中的&&符号并不代表着右值引用,其表示为万能引用,意思就是既能表示为左值引用又能表示为右值引用,而其引用的类型则取决于其接受的参数值类型,左值则使用左值引用,同理反之为右引用。

3.31 完美转发问题

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<class T>
void PerfectForward(T&& t)
{Fun(t);
}

在模板中的万能引用中实际存在着一个问题, 虽然其本身能够接受使用左值、右值两种不同的引用方式,但可能会由于二次传发参数的原因导致参数的性质发生变为,如左值变为右值。

为了解决由于模板中的万能引用&&由于二次传参,导致参数左右值类型发生变化的问题,我们可以使用:forward<类模板>(参数)的形式来保持参数第一次传参时的左右值类型,完成完美转发。

template<class T>
void PerfectForward(T&& t)
{Fun(forward<T>(t));//保持参数t的原生类型属性
}

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

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

相关文章

【原创】java+springboot+mysql在线课程学习网设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

目标检测——YOLO11算法解读

作者&#xff1a;Ultralytics公司 代码&#xff1a;https://github.com/ultralytics/ultralytics YOLO系列算法解读&#xff1a; YOLOv1通俗易懂版解读、SSD算法解读、YOLOv2算法解读、YOLOv3算法解读、YOLOv4算法解读、YOLOv5算法解读、YOLOR算法解读、YOLOX算法解读、YOLOv6算…

FFmpeg的简单使用【Windows】--- 视频倒叙播放

实现功能 点击【选择文件】按钮可以选择视频&#xff0c;当点击【开始处理】按钮之后&#xff0c;会先将视频上传到服务器&#xff0c;然后开始进行视频倒叙播放的处理&#xff0c;当视频处理完毕之后会将输出的文件路径返回&#xff0c;同时在页面中将处理好的视频展示出来。…

第二十三篇:网络拥塞了,TCP/IP如何解决的?

一.显示拥塞通知 当发生网络拥塞时&#xff0c;发送主机应该减少数据包的发送量。作为IP上层协议&#xff0c;TCP虽然也能控制网络拥塞&#xff0c;不过它是通过数据包的实际损坏情况来判断是否发生拥塞。然而这种方法不能在数据包损坏之前减少数据包的发送量。 为了解决这个…

【网络安全】CVE-2024-46990: Directus环回IP过滤器绕过实现SSRF

未经许可,不得转载。 文章目录 背景漏洞详情受影响版本解决方案背景 Directus 是一款开源 CMS,提供强大的内容管理 API,使开发人员能够轻松创建自定义应用程序,凭借其灵活的数据模型和用户友好的界面备受欢迎。然而,Directus 存在一个漏洞,允许攻击者绕过默认的环回 IP …

使用libssh2上传下载文件及Makefile编写

使用libssh2上传下载文件及Makefile编写 一、准备工作二、上传和下载文件三、编写Makefilelibssh2是一个开源的SSH库,用于在C/C++程序中实现SSH2协议的功能。通过libssh2,我们可以方便地进行远程登录、执行命令、上传和下载文件等操作。本文将详细介绍如何使用libssh2库上传和…

【网易云音乐】--源代码分享

最近写了一个网易云音乐的音乐实现部分&#xff0c;是通过JavaScript和jQuery实现的&#xff0c;具体效果大家可以参照下面的视频 源代码分享 - git地址: 网易云音乐源代码 下面将着重讲解一下音乐实现部分 视频有点模糊&#xff0c;不好意思&#xff0c;在b站上添加视频的时候…

全能PDF工具集 | PDF Shaper Ultimate v14.6 便携版

软件简介 PDF Shaper是一款功能强大的PDF工具集&#xff0c;它提供了一系列用于处理PDF文档的工具。这款软件使用户能够轻松地转换、分割、合并、提取页面以及旋转和加密PDF文件。PDF Shaper的界面简洁直观&#xff0c;使得即使是新手用户也能快速上手。它支持广泛的功能&…

基于Nodemcu的手机控制小车

基于Nodemcu的手机控制小车 一、项目说明二、项目材料三、代码与电路设计四、轮子和车体五、电路连接六、使用方法 一、项目说明 嗨&#xff0c;机器人项目制造者们&#xff01;在这个项目中&#xff0c;我制作了这辆简单但快速的遥控车&#xff0c;它可以通过智能手机控制&am…

yum仓库安装rabbitmq

yum仓库安装rabbitmq 1、配置yum仓库 vim /etc/yum.repos.d/rabbitmq.repo # In /etc/yum.repos.d/rabbitmq.repo## ## Zero dependency Erlang ##[rabbitmq_erlang] namerabbitmq_erlang baseurlhttps://packagecloud.io/rabbitmq/erlang/el/7/$basearch repo_gpgcheck1 gpg…

智能生成ppt软件哪个好?如何高效生成ppt?

想要快速制作出专业且吸引人的PPT演示文稿吗&#xff1f;ai智能生成ppt工具可以帮你实现这一目标。 无需复杂的设计技巧&#xff0c;也不必花费大量时间&#xff0c;只需几个简单的步骤&#xff0c;就能创造出令人印象深刻的演示文稿。下面是一份免费版教程&#xff0c;让你轻…

PyCharm+ssh跳板机+服务器

PyCharmssh跳板机服务器 文章目录 PyCharmssh跳板机服务器准备工作登录服务器查看CUDA查看conda创建虚拟环境 前言配置ssh免密登录设置ssh隧道配置pycharm测试第一种第二种 服务器空闲查询传输数据 准备工作 登录服务器 直接ssh连接就行,在终端(命令行)直接输入下面命令: 跳…

K8s-services+pod详解1

一、Service 我们能够利用Deployment创建一组Pod来提供具有高可用性的服务。 虽然每个Pod都会分配一个单独的Pod IP&#xff0c;然而却存在如下两问题&#xff1a; Pod IP 会随着Pod的重建产生变化Pod IP 仅仅是集群内可见的虚拟IP&#xff0c;外部无法访问 这样对于访问这…

基于Python Django的在线考试管理系统

&#x1f34a;作者&#xff1a;计算机毕设匠心工作室 &#x1f34a;简介&#xff1a;毕业后就一直专业从事计算机软件程序开发&#xff0c;至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长&#xff1a;按照需求定制化开发项目…

线程基础学习

线程的实现 通过实现Runnable接口的方式&#xff0c;实现其中的run方法。继承Thread类&#xff0c;然后重写其中的run方法。通过线程池创建线程&#xff0c;默认采用DefaultThreadFactory。有返回值的callable&#xff0c;实现callable接口&#xff0c;实行call方法。 本质上…

【Linux-基础IO】软硬链接+动静态库

一、软硬链接 见一见 软连接 硬连接 通过观察我们发现以下几点&#xff1a; 1.ll - i后&#xff0c;软连接形成的文件有指向&#xff0c;并且软连接的Inode编号与对应文件的Inode编号不一样 2.ll - i后&#xff0c;硬连接形成的文件与对应的文件Inode编号一样 3.软连接…

大佬,简单解释下“嵌入式软件开发”和“嵌入式硬件开发”的区别

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;首先&#xff0c;嵌入式硬…

初识数据结构--时间复杂度 和 空间复杂度

数据结构前言 数据结构 数据结构是计算机存储、组织数据的方式(指不仅能存储数据&#xff0c;还能够管理数据-->增删改)。指相互之间存在一种或多种特定关系的数据元素的集合。没有单一的数据结构对所有用途都有用&#xff0c;所以我们要学习各种的数据结构&#xff0c;比…

visual studio使用ssh连接linux虚拟机运行程序

1.vs安装linux组件 2.安装后新建项目 新建后会有一个使用指南 设置网络为桥接网卡后打开虚拟机 使用vs提升的那句话安装工具 sudo apt-get install openssh-server g gdb gdbserver 重启ssh服务 sudo service ssh restart 接着进去打开ssh端口 sudo vi /etc/ssh/sshd_config …

pytest的基础入门

pytest判断用例的成功或者失败 pytest识别用例失败时会报AssertionError或者xxxError错误&#xff0c;当捕获异常时pytest无法识别到失败的用例 pytest的fixture夹具 pytest的参数化 #coding:utf-8 import pytestfrom PythonProject.pytest_test.funcs.guess_point import ge…