关于右值引用

本文解析了右值引用在C++11中的概念,包括左值和右值的区别,重点讲解了纯右值和将亡值,并阐述了移动语义如何通过资源转移优化内存管理。此外,介绍了移动构造函数和移动赋值函数的应用,以及完美转发的概念及其std::forward模板函数的使用实例。
摘要由CSDN通过智能技术生成

什么是右值引用

右值引用是在c++11标准中提出的,在此之前我们讲的引用都是左值引用。

要想搞明白左值引用和右值引用,首先要区分左值和右值。

在c++11中,右值又分为纯右值和将亡值,纯右值指的是临时变量和不跟对象关联的字面量值,将亡值指的是和右值引用相关的表达式,这样的表达式通常表示将要被移动的对象。

简单一点讲:可以用&去地址的表达式或变量是左值,不能用&取地址的变量或表达式是右值。

比如:

#include<iostream>
using namespace std;

int main()
{
	int a = 8; // a为左值;8为右值
	int& b = a; // b为左值引用
	int&& c = 8; // c为右值引用
	const int& d = 8; // d是一种特殊的左值引用
	cout << "a: " << a << " b: " << b << " c: " << c << " d: " << d << endl;

	//cout << "&a++: " << &a++ << endl;  // a++ 为右值 不能取址
	cout << "&++a: " << &++a << endl;

	return 0;
}

移动语义

移动语义是c++标准中新增的改动,它通过转移资源的方式避免了拷贝带来的资源开销,使内存管理更加细致,当然被转移的一方将不可在使用。代码如下:

#include<iostream>
using namespace std;

class A
{
	public:
		A(){}
		~A()
		{
			delete _ptr;
			_ptr = nullptr;
		}

		void alloc()
		{
			_ptr = new int;
			memset(_ptr, 0, sizeof(int));
		}

		/// 拷贝构造函数
		A(const A& a)
		{
			cout << "拷贝构造调用" << endl;
			if (!_ptr)
				alloc();
			memcpy(_ptr, a._ptr, sizeof(int));
		}

		A& operator= (const A& a)
		{
			cout << "赋值函数调用" << endl;
			if (this == &a)
				return *this;
			if (!_ptr)
				alloc();
			memcpy(_ptr, a._ptr, sizeof(int));
			return *this;
		}

		/// 移动构造函数
		A(A&& a)
		{
			cout << "移动构造函数调用" << endl;
			if (!_ptr)
				delete _ptr;
			_ptr = a._ptr;
			a._ptr = nullptr;
		}

		A& operator= (A&& a)
		{
			cout << "移动赋值函数调用" << endl;
			if (this == &a)
				return *this;
			if (!_ptr)
				delete _ptr;
			_ptr = a._ptr;
			a._ptr = nullptr;
			return *this;
		}

		int* _ptr;
};

int main()
{
	A a;
	a.alloc();
	*a._ptr = 88;

	A a1 = a;
	A a2;
	a2 = a;
	cout << "a2:" << *a2._ptr << endl;

	auto fun = [] {
		A aa;
		aa.alloc();
		*aa._ptr = 99;
		return aa;
	};

	A a3 = fun();
	cout << "a3:" << *a3._ptr << endl;
	A a4;
	a4 = fun();
	cout << "a4:" << *a4._ptr << endl;

	return 0;
}

在类中增加移动构造函数和移动赋值函数,当参数为右值时,会调用对应的函数,将资源转移至目标对象中,避免了拷贝构造函数和赋值函数中拷贝带来的额外开销。记得编译时要用命令 -fno-elide-constructors 把优化关掉,否则编译器会优化fun()的返回。

完美转发

当我们需要通过函数转发变量时,普通方法无法将变量的左值右值属性“完美”转移过去。

c++11中提供了模版函数std::forward<T>(参数),用于完美转发参数的左右值属性。代码:

#include<iostream>
using namespace std;

void fun(int& val)
{
	cout << "左值调用 val:" << val << endl;
}

void fun(int&& val)
{
	cout << "右值调用 val:" << val << endl;
}

template <typename T>
void f(T&& val)
{
	fun(forward<T>(val));
}

int main()
{
	int val = 8;
	f(val);
	f(9);

	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值