亮瞎你的狗眼了吧~这么拗口。 !来补一下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.