【发布时间】:2012-07-28 07:17:07
【问题描述】:
我在 C++11 中的移动语义上阅读了 beautiful article。这篇文章写得很直观。文章中的示例类如下所示。
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( 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;
};
显然,在上述移动构造函数实现中,嵌入元素_metadata 不会发生移动。为了促进这一点,诀窍是像这样使用std::move() 方法。
ArrayWrapper (ArrayWrapper&& other)
: _p_vals( other._p_vals )
, _metadata( std::move( other._metadata ) )
{
other._p_vals = NULL;
}
到目前为止,一切都很好。
标准说:
§5(C++11 §5[expr]/6):
[ 注意:表达式是一个 xvalue 如果它是:
调用函数的结果,无论是隐式还是显式, 其返回类型是对对象类型的右值引用,
对对象类型的右值引用的强制转换,
指定非静态数据成员的类成员访问表达式 对象表达式为 xvalue 的非引用类型,或
.*指向成员的表达式,其中第一个操作数是 xvalue,第二个操作数是指向数据成员的指针。
我的问题:
现在,移动构造函数中的变量other 是一个xvalue(我说的对吗?)。那么根据上面最后一条规则,other._metadata 也应该是一个 xvalue。因此编译器可以隐式使用_metadata 类的移动构造函数。所以,这里不需要std::move。
我错过了什么?
【问题讨论】:
-
最好避免前导下划线以防止意外使用保留名称。
-
养成的好习惯。在这个例子中,没有一个以大写字母开头,所以你没问题,但你很容易忘记不要这样做。
-
@MarkB :这不是我的代码。我只是从引用的文章中复制了它。