我所知道的Move语义与完美转发

我所知道的Move语义与完美转发


一、临时变量效率问题
	
	///
	std::vector<int> f()
	{
		std::vector<int> v;
		// stuff
		return v;
	}
	
	std::vector<int> arr(f());
	//
	
	这部分代码做了三件事情:
	1、 创建v
	2、 用v构造f()的返回值
	3、 用f()的返回值构造arr
	
	问题:在此过程中总共构造了3个v的副本,若能将v直接构造在arr处,就可以避免2次
	不必要的拷贝构造过程。怎么办呢?
	
	在C++11之前,这种构造开销通过RVO(返回值优化)来解决,但是对于如下代码:
	//
	std::vector<int> arr;
	arr = fun();
	//
	编译器就无能为力了。
	
	直到C++11的到来,该问题才被完美解决。
	
二、右值引用
	
	为了解决临时变量的效率问题,C++11引入了“右值引用”。在接下来的文章中,我
	将逐步解释“右值引用”如何成为美貌与智慧并重、英雄与狭义的化身。
		
	左值、右值是表达式的属性,而非对象的属性。左值在表达式结束之后任然存在,而
	右值在表达式结束之后就会析构。
	
	根据右值定义,第一节提到的f()就属于右值。
	
	为了说明后续的问题,我将C++11标准的若干规则罗列如下:	
	
	假设有类型T,T&和const T&表达了传统的左值引用,而T&&表达新引入的右值引用。	
	绑定规则:
	1、const T &和T&&可以绑定到右值;
	2、T&只能绑定左值;
	3、右值优先绑定到T&&;
	
	引用折叠规则:
	T & & ==> T &
	T & && ==> T &
	T && & ==> T &
	T && && ==> T &&
	
	是的,我目前只能告诉你这些规则,至于为什么C++标准这样定义规则是合理的,我
	还没法做出有说服力的回答。
	
三、Move 语义


	还记得std::vector的swap方法么?
	//
	std::vector<int> tmp;
	// tmp stuff
	std::vector<int> arr;
	arr.swap(tmp);
	//
	
	要是能确定tmp不再有用,那么将tmp的内容swap过来是非常优雅和高效的手段。实际上,
	Move semantic 正是这种思想。
	
	问题是怎么表明tmp不再有用?C++11标准库提供了一个方法模板:
	template<typename T>
	std::remove_reference<T>::type && move(T &&);
	
	对于move的实现放在后边的章节解释,目前只需要明白std::move<T>(x)调用返回对x的右值
	引用。	
	
	假设有如下实现的类:
	//
	class M
	{
	public:
		M(std::vector<int> && v)	// move constructor
		{
			m_v = std::move(v);
		}
		
		M(const std::vector<int> & v)
		{
			m_v = v;
		}
		
		M& operator=(std::vector<int> && v) // move assignment
		{
			m_v.swap(v);
		}
		
		M& operator=(const std::vector<int> & v)
		{
			m_v.reserve(v.size());			
			std::copy(m_v.begin(), v.begin(), v.end());
		}
		
		std::vector<int> m_v;
		
		//...
	}
	//	
	
	模板的第一个构造函数称为:move构造函数,形参为右值引用。相对于第二个传统的
	拷贝构造函数,它的实现高效、优雅了太多。
	
	考虑下面的调用
	//
	M m(f());
	
	std::vector<int> tmp;
	m = tmp;
	m = std::move(tmp);
	//	
	根据绑定规则,f()优先绑定到右值引用,因此m将通过move构造函数构造。然后,调用
	普通赋值操作为m赋值,之后又调用move赋值操作为m赋值。
	
四、完美转发
	template<typename T>
	class P
	{
	}
	
	


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值