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