説明:
C 11 で移動セマンティクスを使用する場合、次のことが可能です。デフォルトのコンストラクターが優先されて、移動コンストラクターが予期せずスキップされるシナリオが発生します。この記事では、この問題を調査し、根本的な理由を調べ、解決策を提供します。
問題:
メッセージを出力するコンストラクターを備えた次のクラス X を考えてみましょう:
<code class="cpp">class X { public: explicit X(char* c) { cout << "ctor" << endl; init(c); } X(X& lv) { cout << "copy" << endl; init(lv.c_); } X(X&& rv) { cout << "move" << endl; c_ = rv.c_; rv.c_ = nullptr; } const char* c() { return c_; } private: void init(char *c) { c_ = new char[strlen(c)+1]; strcpy(c_, c); } char* c_; };</code>
以下に示すサンプル使用法では、3 つのオブジェクトを作成します:
<code class="cpp">X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z( X("test") ); cout << z.c() << endl;</code>
ただし、z に対して呼び出される移動コンストラクターを示す予想される出力の代わりに、デフォルトのコンストラクターが代わりに使用されます。
標準への準拠:
C 11 標準 (§12.8.32) に従って、可能な限りコピー セマンティクスよりも移動セマンティクスを優先する必要があります。したがって、この場合、実際に z に対して move コンストラクターを呼び出す必要があります。
動作の説明:
観察された動作は、copy elision。 C 11 では、パフォーマンスを向上させるために、特定の状況でコンパイラがオブジェクトのコピー/移動を省略できるようになります。これらの状況の 1 つは、一時オブジェクトが同じ cv 非修飾型のオブジェクトにコピー/移動される場合です。
解決策:移動コンストラクターを強制的に次のようにします。呼び出されると、std::move() を使用して、移動が行われることを明示的に示すことができます:
<code class="cpp">X z( std::move(X("test")) );</code>この変更により、期待される出力が生成され、移動コンストラクターの関与が確認されます。
以上が一時オブジェクトを使用して別のオブジェクトを初期化するときに、C 11 Move コンストラクターが呼び出されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。