IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 左值引用与右值引用 -> 正文阅读

[C++知识库]左值引用与右值引用

左值与右值

概念
左值与右值是C语言中的概念,但是C标准并没有给出严格的区分方式,一般认为:可以放在 = 左边的(一般是可以修改的值) 或者 能取地址的称为左值只能放在 = 右边(一般是不可修改的一些值),或者不能取地址的值称为右值。(如:常量、临时变量、表达式的返回值)

具体解释:

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

C++11对右值进行了严格的区分:

  • C语言中的纯右值,比如:a+b,100;
  • 将忘值。比如:表达式的中间结果,函数按照值返回的方式进行返回。

左值引用与右值引用

  • 他俩都是给对象取别名;
  • 左值引用一般是给左值取别名,右值引用一般给右值取别名;

左值引用(&) 右值引用(&&)

在这里插入图片描述
那么有没有将左值处理为右值的情况呢??当然是有的!!

move告诉编译器我们有一个左值,但我们希望像一个右值一样处理它。注意:调用move意味着承诺:我们要放弃对move对象的资源管理。
在这里插入图片描述

为什么要提出右值引用呢??它的价值何在??

值的形式返回对象的缺陷

如果一个类中涉及到资源管理,用户必须显式提供拷贝构造、赋值运算符重载以及析构函数,否则编译器将会自动生成一个默认的,如果遇到拷贝对象或者对象之间相互赋值,就会出错,比如:

class String
{
public:
	String(char* str = "")
	{
		//cout << "String()" << endl;
		if (str == nullptr)
		{
			str = "";
		}
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	// 拷贝构造----深拷贝
	String(const String& s)
		:_str(new char[strlen(s.c_str())+1])
	{
		cout << "String(String&)" << endl;
		strcpy(_str, s._str);
	}
	// 移动构造-----移动拷贝
	/*String(String&& s)
		:_str(nullptr)
	{
		cout << "String (String&& s)" << endl;
		std::swap(_str, s._str);
	}*/

	//拷贝赋值----深拷贝
	String& operator=(const String& s)
	{
		cout << "String& operator=(const String& s)" << endl;
		if (this != &s)
		{
			char* tmp = new char[strlen(s.c_str()) + 1];
			strcpy(tmp, s.c_str());
			delete[] _str;
			_str = tmp;
		}
		return *this;
	}
	// 移动赋值----移动拷贝
	/*String& operator=(String&& s)
	{
		cout << "String& operator=(String&& s)" << endl;
		std::swap(_str, s._str);
		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);

		std::swap(_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;

	}
	const char* c_str()const
	{
		return _str;
	}

	~String()
	{
		if (_str)
			delete[] _str;
	}
private:
	char* _str;
};

int main()
{
	String s1("hello");
	String s2("world");
	String s3 = s1 + s2;  // s1+s2,是传值返回,当没有
	String s4 = s1 += s2;
	//cout << endl;

	String s5;
		s5 = s1 + s2;
	
	cout << endl;
	
	String s6;
		s6= s1 += s4;
		
	system("pause");
	return 0;
}

在这里插入图片描述
当然经过编译器优化之后,看起来效率并没有降低,但是接下来这种情况呢??

在这里插入图片描述
那么能否对这种情况进行优化呢????

移动语义

C++11提出了移动语义概念,即:将一个对象中资源移动到另一个对象中的方式,可以有效缓解该问题。
要实现移动语义就必须使用右值引用。
在这里插入图片描述
那上面的例子来说:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

注意:

  1. 移动构造的函数参数千万不能设置程const类型的右值引用,因为资源无法转移而导致移动语义失效。
  2. 再C++11中,编译器会为类默认生成一个移动构造,该移动构造为浅拷贝,因此当类中涉及到资源管理时,用户必须显示定义自己的移动构造。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-22 13:57:27  更:2021-07-22 14:00:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/1 22:19:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码