C++11の移動セマンティクスに関する美しい記事を読みました。この記事は非常に直感的な方法で書かれています。この記事のクラスの例を以下に示します。
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であり、2番目のオペランドがデータメンバーへの
.*
ポインターであるメンバーへのポインター式。
私の質問:
さて、other
moveコンストラクターの変数はxvalueです(私は正しいですか?)。次に、上記の最後のルールに従って、other._metadata
もxvalueである必要があります。したがって、コンパイラは、_metadata
のクラスのmoveコンストラクタを暗黙的に使用できます。だから、std::move
ここにいる必要はありません。
私は何が欠けていますか?