【C++】右值引用

news2024/11/16 11:49:29

文章目录

  • 右值引用
  • 值得形式返回对象的缺陷
  • 移动语句
  • 移动赋值

右值引用

能够取地址、能够被修改的被称之为左值。

不能够取地址、不能够被修改、以及将亡值被称之为右值。

  1. 普通类型的变量,因为有名字,可以取地址,都认为是左值。
  2. const修饰的常量,不可修改,只读类型的,理论应该按照右值对待,但因为其可以取地址(如果只是 const类型常量的定义,编译器不给其开辟空间,如果对该常量取地址时,编译器才为其开辟空间), C++11认为其是左值。
  3. 如果表达式的运行结果是一个临时变量或者对象,认为是右值。
  4. 如果表达式运行结果或单个变量是一个引用则认为是左值。

C++11对右值进行了严格的区分: C语言中的纯右值,比如:a+b, 100 将亡值。比如:表达式的中间结果、函数按照值的方式进行返回。

#include<iostream>
using namespace std;

void test(int a=0)
{
    return a;//a是将亡值
}

int main(void)
{
    int a=10;//a是左值,10是右值
    int b=20;//b是左值,20是右值
    b=a;//左值a也可以放在等于号=右边
    
    return 0;
}

值得形式返回对象的缺陷

#include<iostream>
#include<string>
using namespace std;


class String
{
public:
	String(const char* str = "")
	{
		cout << "构造函数()->String(const char* str = "")" << endl;
		if (nullptr == str)
		str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String & s)
	: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}

	String& operator=(const String& s)
	{
		 if (this != &s)
		 {
			 char* pTemp = new char[strlen(s._str) + 1];
			 strcpy(pTemp, s._str);
			 delete[] _str;
			 _str = pTemp;
		 }	
		return *this;
	}

 String operator+(const String& s)
 {
	 char* pTemp = new char[strlen(_str) + strlen(s._str) + 1];
	 strcpy(pTemp, _str);
	 strcpy(pTemp + strlen(_str), s._str);
	 String strRet(pTemp);
	 return strRet;
 }

 ~String()
 {
	 if (_str) delete[] _str;
 }
private:
	char* _str;
};
int main()
{
	String s1("hello");
	String s2("world");
	String s3=s1 + s2;
	return 0;
}

对于如上代码的operator+中,返回strRet的时候需要临时创建一个对象,然后销毁strRet,最后再把strRets3

这乍一看是没什么问题,但是这里的strRet临时对象s3的内容是完全相同的,但是开辟了三块空间,是不是太浪费空间了。

移动语句

C++11当中,如果需要实现移语句,必须使用右值引用。

#include<iostream>
using namespace std;


class String
{
public:
	String(const char* str = "")
	{
		cout << "构造函数()->String(const char* str = "")" << endl;
		if (nullptr == str)
		str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String & s)
		: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}

	void swap(String& s)
	{
		std::swap(_str,s._str);
	}

	String(String&& s)noexcept
		:_str(nullptr)
	{
		swap(s);
	}


	String& operator=(const String& s)
	{
		 if (this != &s)
		 {
			 char* pTemp = new char[strlen(s._str) + 1];
			 strcpy(pTemp, s._str);
			 delete[] _str;
			 _str = pTemp;
		 }	
		return *this;
	}

 String operator+(const String& s)
 {
	 char* pTemp = new char[strlen(_str) + strlen(s._str) + 1];
	 strcpy(pTemp, _str);
	 strcpy(pTemp + strlen(_str), s._str);
	 String strRet(pTemp);
	 return strRet;
 }

 ~String()
 {
	 if (_str) delete[] _str;
 }
private:
	char* _str;
};
int main()
{
	String s1("hello");
	String s2("world");
	String s3=(s1 + s2);
	return 0;
}

代码添加一个移动构造,就可以减少申请空间,在strRet返回的时候会去调用String(String&& s)noexcept,调用String(String&& s)noexcept的时候可以看到,直接把sthis中的资源做了交换,出了作用域,s就会被销毁,那么在销毁之前把资源先给this不是就可以减少拷贝了吗?

移动赋值

移动赋值和移动构造一样,可以减少拷贝,将现有的资源最大利用,减少空间的开辟。

#include<iostream>
using namespace std;


class String
{
public:
	String(const char* str = "")
	{
		cout << "构造函数()->String(const char* str = "")" << endl;
		if (nullptr == str)
		str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}

	String(const String & s)
		: _str(new char[strlen(s._str) + 1])
	{
		strcpy(_str, s._str);
	}

	void swap(String& s)
	{
		std::swap(_str,s._str);
	}

	//移动构造
	String(String&& s)noexcept
		:_str(nullptr)
	{
		cout << "移动构造(资源移动)" << endl;
		swap(s);
	}

	// 移动赋值
	String& operator=(String&& s)noexcept
	{
		cout << "String& operator=(string s) -- 移动赋值(资源移动)" << endl;
		swap(s);

		return *this;
	}


	String& operator=(const String& s)
	{
		 if (this != &s)
		 {
			 char* pTemp = new char[strlen(s._str) + 1];
			 strcpy(pTemp, s._str);
			 delete[] _str;
			 _str = pTemp;
		 }	
		return *this;
	}

 String operator+(const String& s)
 {
	 char* pTemp = new char[strlen(_str) + strlen(s._str) + 1];
	 strcpy(pTemp, _str);
	 strcpy(pTemp + strlen(_str), s._str);
	 String strRet(pTemp);
	 return strRet;
 }

 ~String()
 {
	 if (_str) delete[] _str;
 }
private:
	char* _str;
};
int main()
{
	String s1("hello");
	String s2("world");
	String s3=(s1 + s2);
	s3 = move(s1);//强行转换成将亡值
	return 0;
}

这里的move就是强制类型转化成一个将亡值,让其变成右值,好去调用我们这里的移动赋值(这里只是为了强行调用移动赋值,这样的代码其实是有问题的,会导致s1变成nullptr)。

move(s1)==static_cast<String&&>(s1);

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

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

相关文章

MyBatis查询数据库(4)

前言&#x1f36d; ❤️❤️❤️SSM专栏更新中&#xff0c;各位大佬觉得写得不错&#xff0c;支持一下&#xff0c;感谢了&#xff01;❤️❤️❤️ Spring Spring MVC MyBatis_冷兮雪的博客-CSDN博客 终于到了MyBatis最后一篇&#xff0c;这篇讲的是动态SQL的使用。 复杂情…

docker配置远程连接端口

配置docker 配置远程连接端口 vi /lib/systemd/system/docker.servicesystemctl daemon-reload && systemctl restart docker firewall-cmd --zonepublic --add-port2375/tcp --permanenthttp://node2:2375/version

【类和对象】基础知识

目录 一、类的定义 定义方式一&#xff1a;定义与声明都在类中 定义方式二&#xff1a;定义与声明分离 二、类的实例化&&类对象存储方式 类的实例化 类对象存储模式 三、this指针 一、类的定义 定义方式一&#xff1a;定义与声明都在类中 #include<iostream&…

深入学习 Redis - 谈谈你对 Redis 的 RDB、AOF、混合持久化的了解吧?

目录 一、Redis 是怎么存储数据的&#xff1f; 二、Redis 具体是按照什么样的策略来实现持久化的&#xff1f; 2.1、RDB&#xff08;Redis Database&#xff09; 2.1.1、触发机制 2.1.2、bgsave 命令处理流程 2.1.3、RDB 文件的处理 2.1.4、演示效果 1&#xff09;手动执…

GEE:谐波模型在遥感影像中的应用(季节性变化的拟合与可视化)

作者:CSDN @ _养乐多_ 谐波模型是一种常用的工具,用于拟合和分析影像数据中的周期性和季节性变化。本文将介绍如何使用Google Earth Engine平台实现谐波模型,通过对Landsat影像进行处理和拟合,展示季节性变化的拟合结果,并通过图表和地图可视化展示数据。 谐波模型是一种…

《Java-SE-第二十九章》之Synchronized原理与JUC常用类

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水平很有限&…

OpenAI 已为 GPT-5 申请商标,GPT-4 发布不到半年,GPT-5 就要来了吗?

据美国专利商标局&#xff08;USPTO&#xff09;信息显示&#xff0c;OpenAI已经在7月18日申请注册了“GPT-5”商标。 在这份新商标申请中&#xff0c;OpenAI将“GPT-5”描述为一种“用于使用语言模型的可下载计算机软件”。 继GPT-4发布之后&#xff0c;它预计将成为OpenAI下一…

【硬件设计】模拟电子基础三--放大电路

模拟电子基础三--放大电路 一、集成运算放大器1.1 定义、组成与性能1.2 电流源电路1.3 差动放大电路1.4 理想运算放大器 二、集成运算放大器的应用2.1 反向比例运算电路2.2 同向比例运算电路2.3 反向加法运算电路2.4 反向减法运算电路2.5 积分运算电路2.6 微分运算电路2.7电压比…

备战秋招 | 笔试强训23

目录 一、选择题 二、编程题 三、选择题题解 四、编程题题解 一、选择题 1、2 —3—6—7—8—14—15—30&#xff0c;下面的数字哪一个是不属于这组数字的系列? A. 3 B. 7 C. 8 D. 15 2、下列关于线性链表的叙述中&#xff0c;正确的是&#xff08; &#xff09; A. 各数…

【数理知识】协方差,随机变量的的协方差,随机变量分别是单个数字和向量时的协方差

序号内容1【数理知识】自由度 degree of freedom 及自由度的计算方法2【数理知识】刚体 rigid body 及刚体的运动3【数理知识】刚体基本运动&#xff0c;平动&#xff0c;转动4【数理知识】向量数乘&#xff0c;内积&#xff0c;外积&#xff0c;matlab代码实现5【数理知识】协…

Java上传文件图片到阿里云OSS

开通阿里云OSS 进入阿里云官网&#xff0c;开通对象存储 OSS服务进入对象存储 OSS管理控制台&#xff0c;在Bucket 列表中创建Bucket 在AccessKey管理中创建AccessKey ID和AccessKey Secret。保存起来&#xff0c;代码中需要 代码开发 pom引入依赖 <!-- 阿里云OSS -->…

Java的变量与常量

目录 变量 声明变量 变量的声明类型 变量的声明方式&#xff1a;变量名 变量名的标识符 初始化变量 常量 关键字final 类常量 总结 变量和常量都是用来存储值和数据的基本数据类型存储方式&#xff0c;但二者之间有一些关键差别。 变量 在Java中&#xff0c;每个变…

架构训练营学习笔记:5-2 负载均衡架构

多级负载架构 设计关键点 性能需求、维护复杂度之间做取舍。 一可以去掉F5、LVS &#xff1a; F5 是成本较高&#xff0c;LVS 是复杂&#xff0c;对于性能没那么高需求&#xff0c;可以去掉。 二 去掉ng: 服务网关服务 适应于初创公司快速验证&#xff0c;内部的 小系统…

深入解析人脸识别技术:原理、应用与未来发展

人脸识别技术&#xff1a;从原理到应用 引言人脸识别技术的重要性和应用领域 人脸识别的基本原理图像采集与预处理特征提取与表征数据匹配与比对 传统人脸识别方法主成分分析&#xff08;PCA&#xff09;线性判别分析&#xff08;LDA&#xff09;小波变换在人脸识别中的应用 深…

论文笔记:SUPERVISED CONTRASTIVE REGRESSION

2022arxiv的论文&#xff0c;没有中&#xff0c;但一作是P大图班本MIT博&#xff0c;可信度应该还是可以的 0 摘要 深度回归模型通常以端到端的方式进行学习&#xff0c;不明确尝试学习具有回归意识的表示。 它们的表示往往是分散的&#xff0c;未能捕捉回归任务的连续性质。…

mysql8配置binlog日志skip-log-bin,开启、关闭binlog,清理binlog日志文件

1.概要说明 binlog 就是binary log&#xff0c;二进制日志文件&#xff0c;这个文件记录了MySQL所有的DML操作。通过binlog日志我们可以做数据恢复&#xff0c;增量备份&#xff0c;主主复制和主从复制等等。对于开发者可能对binlog并不怎么关注&#xff0c;但是对于运维或者架…

continue有什么作用

学习算法以来&#xff0c;break使用的比较多&#xff0c;continue使用的比较少&#xff0c;只知道break是跳出循环的作用,不知道continue有什么作用。 continue可以跳过本次循环&#xff0c;强制执行下一次循环。 比如这个代码 #include<iostream>using namespace std…

开源进展 | WeBASE v3.1.0发布,新增多个实用特性

WeBASE是一个友好、功能丰富的区块链中间件平台&#xff0c;通过一系列通用功能组件和实用工具&#xff0c;助力社区开发者更快捷地与区块链进行交互。 目前WeBASE已更新迭代至v3.1.0版本&#xff0c;本次更新中&#xff0c;WeBASE带来了最新的合约Java脚手架导出功能&#xff…

U盘连接电脑显示为灰色怎么办?

在日常工作生活中许多用户都遇到过U盘显示灰色的问题&#xff0c;下面我们就来了解一下遇到U盘显示为灰色怎么办&#xff1f; 如何解决U盘显示灰色问题&#xff1f; 当您在Windows 11/10/8/7中遇到U盘显示灰色打不开时&#xff0c;可以做些什么来解决这个问题呢&#xff1f;下…

redis的缓存更新策略

目录 三种缓存更新策略 业务场景&#xff1a; 主动更新的三种实现 操作缓存和数据库时有三个问题 1.删除缓存还是更新缓存&#xff1f; 2.如何保证缓存与数据库的操作的同时成功或失败&#xff1f; 3.先操作缓存还是先操作数据库&#xff1f; 缓存更新策略的最佳实践方案&am…