【C++】右值引用详解(移动构造、移动赋值、万能引用和完美转发、关键字default和delete)

文章详细介绍了C++11中的右值引用,包括左值和右值的概念,右值引用的作用,如减少拷贝提高效率,以及右值引用的左值属性。此外,还讨论了万能引用和完美转发的概念,以及默认移动构造和移动赋值的使用。

1、区分左右值

什么是左值?
左值是一个数据的表达式,能被取地址和赋值。
左值引用就是给左值取别名。

int main()
{
   
   
	//以下a、b、p、*p都是左值
	int a = 1;
	const int b = 2;
	int* p = new int;

	//以下ra、rb、rp、value都是左值引用
	//并且看到左值a、b、p、*p也都可以出现在赋值右边
	//所以左值既可以在赋值左边,也可以在赋值右边
	int& ra = a;
	const int& rb = b;
	int*& rp = p;
	int& value = *p;
}

左值重点:
能被取地址的才是左值。
左值既可以出现在赋值左边,也可以出现在赋值右边。

什么是右值?
右值也是一个数据的表达式,右值不能取地址,如:字面常量、表达式返回值,函数返回值等

int main()
{
   
   
	int x = 1, y = 2;
	//这种字面值常量、函数返回值、表达式都是右值
	10;
	fmin(1, 2);
	x + y;

	//右值引用只能引用右值
	int&& rra = 10;
	int&& rrm = fmin(1, 2);
	int&& rrb = x + y;
}

右值不能被取地址
右值只能放在赋值右边

左值引用能引用左值和右值,右值引用只能引用右值
左值引用是给左值取别名,右值引用是给右值取别名。

int main()
{
   
   
	int x = 1, y = 2;

	int a = 1;
	//const左值引用能引用左值
	const int& ra = a;

	//const左值引用能引用右值 本质是权限的缩小
	const int& rb = x + y;
	const int& rc = 10;

	//右值引用只能引用右值
	int&& rrd = x + y;
	//int&& rrd = a; //err 无法将右值引用绑定到左值
	
	//但是右值引用能引用move修饰的左值
	int&& rre = move(a);
}

左值引用能引用左值
const左值引用即能引用左值,也能引用右值


右值引用除了引用右值,还可以引用move修饰后的左值。

2、右值引用

左值引用的意义是什么? 函数传参/函数传返回值 – 减少拷贝

template<class T>
void func1(const T& x)
{
   
   
	// ...
}

template<class T>
const T& func2(const T& x)
{
   
   
	// ...
	return x;
}

但是左值引用没有彻底解决函数中局部对象返回的问题:

template<class T>
T func3(const T& x)
{
   
   
	T temp;
	// ...
	return temp;
}

右值引用的意义就是为了补齐这个短板

2.1 右值引用的作用

先来看一段代码

#include <iostream>
#include <assert.h>
using namespace std;
namespace test
{
   
   
	class string
	{
   
   
	public:
		typedef char* iterator;
		iterator begin()
		{
   
   
			return _str;
		}

		iterator end()
		{
   
   
			return _str + _size;
		}

		string(const char* str = "")
			:_size(strlen(str))
			, _capacity(_size)
		{
   
   
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}

		// s1.swap(s2)
		void swap(string& s)
		{
   
   
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}

		// 拷贝构造
		string(const string& s)
		{
   
   
			cout << "string(const string& s) -- 深拷贝" << endl;

			string tmp(s._str);
			swap(tmp);
		}

		// 赋值重载
		string& operator=(const string& s)
		{
   
   
			cout << "string& operator=(string s) -- 深拷贝" << endl;
			string tmp(s._str);
			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)
		
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值