C 11 Move Constructor Not Called, Default Constructor Preferred
特定のシナリオでは、C 11 Move コンストラクターが呼び出されず、代わりにデフォルトのコンストラクターを使用します。その理由を理解するために、例を見てみましょう。
次のクラスについて考えてみましょう。
<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>
このクラスを使用すると、次のようにオブジェクトを作成できます。
<code class="cpp">int main() { X x("test"); cout << x.c() << endl; X y(x); cout << y.c() << endl; X z( X("test") ); cout << z.c() << endl; return 0; }</code>
期待される出力は次のようになります:
ctor test copy test ctor <-- Why not move? test
ただし、移動コンストラクターが最後の行で呼び出されないことがわかります。代わりに、デフォルトのコンストラクターが使用されます。これを説明するには、コピー省略を理解する必要があります。
コピー省略は、特定の条件下で C 11 標準で許可されている最適化手法です。これにより、コンパイラーは、コピー/移動コンストラクターとデストラクターのオーバーヘッドを回避して、一時オブジェクトをターゲット オブジェクトに直接構築できるようになります。
この例では、一時的な「テスト」から作成された X オブジェクトが z に省略されます。これは、コピー/移動コンストラクターが呼び出されず、代わりにオブジェクトが z に直接構築されることを意味します。
次の条件がすべて満たされると、コンパイラーはコピー省略を実行することがあります。
この場合、これらの条件が満たされるため、コピー省略が発生し、移動コンストラクターの代わりにデフォルトのコンストラクターが使用されます。 move コンストラクターを明示的に呼び出すには、次のように std::move を使用できます。
<code class="cpp">X z( std::move(X("test")) );</code>
以上が一時オブジェクトからオブジェクトを作成するときに C 11 Move コンストラクターが呼び出されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。