“右值引用”不是”右值”,而是”左值”

亮瞎你的狗眼了吧~这么拗口。 !来补一下C++基础吧~~

右值引用 rvalue reference

右值 rvalue

左值 lvalue

什么是左值 lvalue呢。

本质上,左值是一个可以拿到其地址的表达式。左值lvalue里的l,本质上是locatable的缩写,因为lvalue通常可以放置于表达式的左边,于是就有了左left值的说法。

In C++, an lvalue is an expression whose address can be taken, essentially it's a locator value.

class MetaData
{
public:
	MetaData (int size, const std::string& name)
		: _name( name )
		, _size( size )
	{}

	// copy constructor
	MetaData (const MetaData& other)
		: _name( other._name )
		, _size( other._size )
	{
		cout << "copy\n";
	}

	// move constructor
	MetaData (MetaData&& other)
		: _name( other._name )
		, _size( other._size )
	{
		cout << "move\n";
	}

	std::string getName () const { return _name; }
	int getSize () const { return _size; }
private:
	std::string _name;
	int _size;
};

class ArrayWrapper
{
public:
	// default constructor produces a moderately sized array
	ArrayWrapper ()
		: _p_vals( new int[ 64 ] )
		, _metadata( 64, "ArrayWrapper" )
	{}

	ArrayWrapper (int n)
		: _p_vals( new int[ n ] )
		, _metadata( n, "ArrayWrapper" )
	{}

	// move constructor
	ArrayWrapper (ArrayWrapper&& other)
		: _p_vals( other._p_vals  )
		, _metadata( move(other._metadata ))
	{
		other._p_vals = NULL;
	}

	// copy constructor
	ArrayWrapper (const ArrayWrapper& other)
		: _p_vals( new int[ other._metadata.getSize() ] )
		, _metadata( other._metadata )
	{
		for ( int i = 0; i < _metadata.getSize(); ++i )
		{
			_p_vals[ i ] = other._p_vals[ i ];
		}
	}
	~ArrayWrapper ()
	{
		delete [] _p_vals;
	}
private:
	int *_p_vals;
	MetaData _metadata;
};

ArrayWrapper get()
{
	ArrayWrapper aw;
	return aw;
}

int main()
{
	ArrayWrapper aw(get());
	return 0;
}

这段代码中的ArrayWrapper的移动构造函数能工作吗?

错!答案是不能~ 更详细,请参考:http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html

概括地讲,本质原因是因为:右值引用不是右值,而是左值。所以ArrayWrapper里的移动构造函数不会调用ArrayWrapper内嵌的MetaData的移动构造函数,而是调用它MetaData的复制构造函数。为了得到期望的行为,需要使用std::move把lvalue转换成rvalue.

 

Leave a Reply

Your email address will not be published. Required fields are marked *