移動のセマンティクスとコピー/移動の省略を理解しようとしています。
いくつかのデータをラップするクラスが欲しいです。コンストラクターでデータを渡したいのですが、データを所有したいと思います。
this、this、およびthisを読んだ後、C++ 11 でコピーを保存する場合、値渡しは少なくとも他のオプションと同じくらい効率的である必要があるという印象を受けました (コードサイズの増加という小さな問題は別として) )。
次に、呼び出し元のコードがコピーを回避したい場合は、左辺値の代わりに右辺値を渡すことでできます。(例: std::move を使用)
だから私はそれを試しました:
#include <iostream>
struct Data {
Data() { std::cout << " constructor\n";}
Data(const Data& data) { std::cout << " copy constructor\n";}
Data(Data&& data) { std::cout << " move constructor\n";}
};
struct DataWrapperWithMove {
Data data_;
DataWrapperWithMove(Data&& data) : data_(std::move(data)) { }
};
struct DataWrapperByValue {
Data data_;
DataWrapperByValue(Data data) : data_(std::move(data)) { }
};
Data
function_returning_data() {
Data d;
return d;
}
int main() {
std::cout << "1. DataWrapperWithMove:\n";
Data d1;
DataWrapperWithMove a1(std::move(d1));
std::cout << "2. DataWrapperByValue:\n";
Data d2;
DataWrapperByValue a2(std::move(d2));
std::cout << "3. RVO:\n";
DataWrapperByValue a3(function_returning_data());
}
出力:
1. DataWrapperWithMove:
constructor
move constructor
2. DataWrapperByValue:
constructor
move constructor
move constructor
3. RVO:
constructor
move constructor
これらのケースのいずれでもコピー コンストラクターが呼び出されないことを嬉しく思いますが、2 番目のケースで呼び出される余分な移動コンストラクターがあるのはなぜですか? まともな移動コンストラクターはData
かなり速いはずだと思いますが、それでも私はくすくす笑っています。代わりに右辺値参照渡し (最初のオプション) を使用したくなります。これにより、移動コンストラクターの呼び出しが 1 つ少なくなるように思われますが、可能であれば、値渡しとコピー省略を採用したいと考えています。