私は C++11 の右辺値参照と移動セマンティクスを理解しようとしています。
これらの例の違いは何ですか? また、ベクターコピーを行わないのはどれですか?
最初の例:
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> &&rval_ref = return_vector();
2番目の例:
std::vector<int>&& return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();
3番目の例:
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();
ベストアンサー1
最初の例
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> &&rval_ref = return_vector();
最初の例は、 によってキャッチされる一時オブジェクトを返しますrval_ref
。その一時オブジェクトの有効期間は定義を超えて延長されrval_ref
、値によってキャッチしたかのように使用できます。これは次の例と非常によく似ています。
const std::vector<int>& rval_ref = return_vector();
ただし、私の書き直しでは、明らかにrval_ref
非 const 方式で使用することはできません。
2番目の例
std::vector<int>&& return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();
2 番目の例では、実行時エラーが発生しています。関数内ではrval_ref
、破棄されたオブジェクトへの参照が保持されますtmp
。運が良ければ、このコードはすぐにクラッシュします。
3番目の例
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return std::move(tmp);
}
std::vector<int> &&rval_ref = return_vector();
3 番目の例は、最初の例とほぼ同等です。on はstd::move
不要tmp
であり、戻り値の最適化を妨げるため、実際にはパフォーマンスが低下する可能性があります。
実行していることをコード化する最良の方法は次のとおりです。
ベストプラクティス
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> rval_ref = return_vector();
つまり、C++03の場合と同じです。tmp
戻り値ステートメントでは暗黙的に右辺値として扱われます。戻り値最適化(コピーなし、移動なし)によって返されるか、コンパイラがRVOを実行できないと判断した場合は、ベクターの移動コンストラクタを使用して戻り値を返しますRVO が実行されず、返される型に移動コンストラクターがない場合のみ、戻り値にコピー コンストラクターが使用されます。