左值引用、右值引用及移动语义

个人主页:Lei宝啊 

愿所有美好如期而遇


左值

概念

可以取到地址的值就是左值,并且一般情况下可以修改(const类型左值不可修改)。

左值举例:

//左值
int a = 0;
const int b = 1;
int* p = &a;

右值

概念

不能取到地址的值就是右值,并且右值不能被修改。(字面常量,表达式返回值,函数返回值(非左值引用)),我们之前使用的就是左值引用。

右值举例:

int func()
{return 1 + 1;
}//右值
10;
a + b;
func();

左值引用

概念

左值引用就是给左值的引用,给左值取别名。
int a = 0;const int b = 1;int* p = &a;//左值引用int& c = a;const int& d = b;int*& e = p;

右值引用

概念

右值引用就是给右值的引用,给右值取别名。

	10;a + b;func();//右值引用int&& e = 10;int&& f = a + b;int&& g = func();

互相引用 

左值引用右值需要加const,右值引用左值需要将左值先进行move。

	//左值引用右值const int& f = 10;//右值引用左值int&& g = move(a);

应用与解释

简单来说就是为什么需要右值引用,我们先来看例子:

也就是说,临时对象的产生其实是多余的,所以在没有右值引用时,编译器给出的优化方案就是优化掉临时对象,直接使func中vv拷贝构造main中vv,可即便如此,还是有一次无谓的拷贝,就是func中的vv,他仍要销毁,资源还是浪费了。

接下来使用我们自己实现的string,来对有无右值引用做对比。

#include <iostream>
#include <string>
#include <string.h>
#include <cassert>
#include <algorithm>using namespace std;namespace own
{class string{public:typedef char* iterator;iterator begin(){return _str;}iterator end(){return _str + _size;}string(const char* str = ""):_size(strlen(str)), _capacity(_size){//cout << "string(char* str)" << endl;_str = new char[_capacity + 1];strcpy(_str, str);}// s1.swap(s2)void swap(string& s){::swap(_str, s._str);::swap(_size, s._size);::swap(_capacity, s._capacity);}// 拷贝构造 -- 左值string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;_str = new char[s._capacity+1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}// 拷贝赋值// s2 = tmpstring& operator=(const string& s){cout << "string& operator=(const string& s) -- 深拷贝" << endl;string tmp(s);swap(tmp);return *this;}~string(){delete[] _str;_str = nullptr;}char& operator[](size_t pos){assert(pos < _size);return _str[pos];}void reserve(size_t n){if (n > _capacity){char* tmp = new char[n + 1];strcpy(tmp, _str);delete[] _str;_str = tmp;_capacity = n;}}void push_back(char ch){if (_size >= _capacity){size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;reserve(newcapacity);}_str[_size] = ch;++_size;_str[_size] = '\0';}//string operator+=(char ch)string& operator+=(char ch){push_back(ch);return *this;}const char* c_str() const{return _str;}private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0; // 不包含最后做标识的\0};own::string to_string(int value){bool flag = true;if (value < 0){flag = false;value = 0 - value;}own::string str;while (value > 0){int x = value % 10;value /= 10;str += ('0' + x);}if (flag == false){str += '-';}std::reverse(str.begin(), str.end());return str;}
}

这里博主使用g++编译器,并且关闭了部分优化,在Visual  Studio 2022中,优化非常大,我们看不出他的过程,无法更好地进行对比,所以这里在Linux下进行演示,并使用-fno-elide-constructors关闭g++的编译优化。

举例一:仅有左值引用

一:
int main()
{own::string ret = own::to_string(1234);return 0;
}

这也就是我们上面得出的结果。

二:
int main()
{own::string ret;ret = own::to_string(-1234);return 0;
}

这种编译器是不会优化的,所以一般来说将他们写在一行上。

举例二:加入右值引用

		// 移动构造 -- 右值(将亡值)string(string&& s){cout << "string(string&& s) -- 移动拷贝" << endl;swap(s);}

我们这里为什么要加入右值引用呢?首先,右值也叫做将亡值,也就是即将销毁的值。我们希望能够将这个将亡值利用起来,拿走他的资源。

我们可以想象一下,可以拿走左值的资源吗?左值引用左值,左值可能仍要被使用,如果这么被swap拿走资源是不可以的,但是将亡值,也就是对右值这样做却是我们希望看到的。 

一:
int main()
{own::string ret = own::to_string(1234);return 0;
}

这和我们上面的结果是一致的。

二:
int main()
{own::string ret;ret = own::to_string(-1234);return 0;
}

加入移动赋值拷贝

		// 移动赋值string& operator=(string&& s){cout << "string& operator=(string&& s) -- 移动拷贝" << endl;swap(s);return *this;}
三:
int main()
{own::string ret;ret = own::to_string(-1234);return 0;
}

看了这么久也许你有一个疑惑,移动构造和移动赋值,都要交换右值的资源,但是右值不是不能被修改吗?

那么这里我们说:右值引用 引用右值后的属性为左值。

也就是说,一个右值,被右值引用后,那个右值引用的属性将变成左值,于是swap中的s属性是左值,也就可以传过去了。

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

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

相关文章

三相四线智能电表直接接入式接线图

大家好&#xff0c;今天我们要聊的是三相四线智能电表的直接接入式接线方式。别担心&#xff0c;我会用简单易懂的语言来解释这个看似复杂的主题。 首先&#xff0c;我们得知道什么是三相四线电表。在我们的生活中&#xff0c;电力供应通常分为单相和三相。三相电&#xff0c;就…

vue 下载图片/视频到浏览器

方法1&#xff1a;直接在当前页面打开图片或者视频 window.location.href url;//借用a标签实现同样效果 const link document.createElement(a) link.href url // 文件地址 link.click(); 方法2&#xff1a;新开一个窗口打开图片或视频 window.open(url); 方法3&#xf…

分页-PageHelper原理以及实时分页-键集分页

一.PageHelper原理 1.使用 PageHelper 是国内非常优秀的一款开源 mybatis 分页插件&#xff0c;它支持常用的主流数据库&#xff0c;例如 Oracle、Mysql、MariaDB、SQLite、Hsqldb 等。 PageHelper 的安装很简单&#xff0c;只需要在 pom.xml 中加入以下依赖即可&#xff1a…

网络类型及数据链路层协议

目录 一、网络的分类 二、数据链路层协议 1、MA网络以太网协议 2、P2P网络 3、HDLC ---高级数据链路控制协议 HDLC地址借用 三、PPP协议 1、PPP协议的优点 2、PPP数据帧封装结构 3、PPP会话的搭建 4、LCP建立——链路建立阶段 4.1协商阶段 4.2认证阶段 4.3 PAP---密…

深入聊聊企业数字化转型这个事儿

01 什么是数字化&#xff1f; 聊数字化&#xff0c;就不得不聊聊信息化、智能化。佛性的说&#xff1a;信息化是数字化的前世&#xff0c;智能化是数字化的来生&#xff01;我习惯用一个结构化的图形来表示事物之间的关系&#xff0c;信息化、数字化、智能化的关系如下&#…

尤大大正式官宣推出VitePress 1.0

VitePress 在现代Web开发领域&#xff0c;构建快速、响应式的文档网站是开发者经常面临的任务之一。VitePress应运而生&#xff0c;它结合了Vue.js和Vite的强大功能&#xff0c;为开发者提供了一个简单易用的静态站点生成器。Vue.js作为一种流行的前端框架&#xff0c;以其简洁…

网络安全:Kali Linux 进行SQL注入与XSS漏洞利用

目录 一、实验 1.环境 2.Kali Linux 进行SQL注入 3.Kali Linux 进行XSS漏洞利用 二、问题 1.XSS分类 2.如何修改beef-xss的密码 3.beef-xss 服务如何管理 4.运行beef报错 5.beef 命令的颜色有哪些区别 6.owasp-top-10 有哪些变化 一、实验 1.环境 &#xff08;1&a…

30---SDRAM电路设计

视频链接 SDRAM电路设计01_哔哩哔哩_bilibili SDRAM电路设计 1、SDRAM简介 SDRAM&#xff1a;Synchronous Dynamic Random Access Memory&#xff0c;同步动态随机存储器。 同步是指其时钟频率和CPU前端总线的系统时钟相同&#xff0c;并且内部命令的发送与数据的传输都以…

如何避免SQL注入攻击?

&#x1f413;序言 当涉及到数据库操作时&#xff0c;防止SQL注入攻击至关重要。SQL注入是一种常见的网络安全威胁&#xff0c;攻击者通过在用户输入中插入恶意的SQL代码&#xff0c;从而可以执行未经授权的数据库操作。 &#x1f413;避免方式 使用参数化查询 使用参数化查询…

【漏洞复现】用友U8 login2.RegisterServlet接口处存在SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

MyBatis3源码深度解析(二十五)级联映射与关联查询(二)级联映射的实现原理

文章目录 前言10.2 MyBatis级联映射的实现原理10.2.1 ResultMap详解10.2.2 ResultMap解析过程10.2.3 级联映射的实现原理10.2.3.1 handleRowValuesForSimpleResultMap()10.2.3.2 handleRowValuesForNestedResultMap() 前言 上一节【MyBatis3源码深度解析(二十四)级联映射与关联…

为什么Solana在区块链生态系统中脱颖而出

当我们在不断发展的区块链技术世界中航行时&#xff0c;认识到平台不仅要跟上创新的步伐&#xff0c;还要突破可能的界限&#xff0c;这一点至关重要。#Solana 已成为领先的竞争者&#xff0c;这就是为什么这个高性能区块链的未来看起来很光明。 &#x1f31f; 可扩展性和速度&…

单臂路由和三层交换机

目录 一.单臂路由 1.单臂路由的工作原理 2.单臂路由的配置 2.1画出拓扑图 2.2配置PC 2.3配置交换机 2.4配置路由器 2.5测试 二.三层交换机 1.三层交换机的概述 2.三层交换机的配置 2.1画出拓扑图 2.2配置PC 2.3配置二层交换机 2.4配置三层交换机 2.5测试 3.拓展 三.总结 一.…

Trello国内替代工具有哪些?分享5款

盘点5款类似Trello的本地部署项目管理工具&#xff1a;1.PingCode&#xff1b;2.Worktile&#xff1b;3.Teambition&#xff1b;4.redmine&#xff1b;5.TAIga.io。 Trello是一款杰出的协作与工作管理应用&#xff0c;专为追踪团队项目、凸显当前活动任务、分配责任人&#xff…

web全栈架构师第16期教程

教程介绍 互联网时代已进入后半场&#xff0c;行业环境发生了显著变化。互联网人&#xff0c;尤其是技术人员&#xff0c;如何在加速更迭的技术浪潮中持续充电&#xff0c;提升自身价值&#xff0c;是当下必须面对的挑战。课程涉及了现下前端实际开发时所需要的各块内容&#…

编程语言|C语言——C语言基本数据类型

前言 针对不同的数据&#xff0c;采取不同的存储方式和进行不同的处理。随着处理对象的复杂化&#xff0c;数据类型也要变得更丰富。数据类型的丰富程度直接反映了程序设计语言处理数据的能力。 C语言很重要的一个特点是它的数据类型十分丰富。因此&#xff0c;C语言程序数据处…

求解vue3警告

Invalid prop: type check failed for prop “activeType”. Expected TheTypedFn, got Number with value 0. 警告 复现问题 从demo.vue跳转到after-sale/index.vue页面 //demo.vue <div v-for"(obj, index) in list" :key"index" style"margi…

【Altium】ADTOP层器件如何变更到Bottom层及层颜

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 AD22 PCB TOP层器件变更到Bottom层及Bottom颜色的修改 2、 问题场景 在PCB布局评估设计时&#xff0c;考虑到器件布局摆放的合理性&#xff0c;有些器件需要布局放置在Bottom层&#xff0c;另外根据个人的设计风格习…

【hexo博客6】自定义域名 购买、配置、更新部署

【hexo博客6】自定义域名 购买、配置、更新部署 写在最前面自定义域名购买域名DNS配置Github 配置 更新部署博客 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#…

MySQL的安装(Linux版)

1.所需要的文件 MySQL.zip 2. 卸载自带的Mysql-libs # 查看是否存在 rpm -qa | grep mariadb# 如果存在则执行命令进行卸载 rpm -e --nodeps mariadb-libs3.在/opt目录下创建MySQL目录并上传所需要的安装包 cd /optmkdir MySQL4.按照编号顺序安装&#xff08;压缩包在解压完…