ホームページ  >  記事  >  バックエンド開発  >  一時オブジェクトからオブジェクトを作成するときに C 11 Move コンストラクターが呼び出されないのはなぜですか?

一時オブジェクトからオブジェクトを作成するときに C 11 Move コンストラクターが呼び出されないのはなぜですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-11-04 19:17:02215ブラウズ

Why isn't the C  11 Move Constructor Called When Creating an Object from a Temporary Object?

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 に直接構築されることを意味します。

次の条件がすべて満たされると、コンパイラーはコピー省略を実行することがあります。

  • オブジェクトは、参照にバインドされていない一時オブジェクトです。
  • オブジェクトは、同じ cv 非修飾型のオブジェクトにコピーまたは移動されます。

この場合、これらの条件が満たされるため、コピー省略が発生し、移動コンストラクターの代わりにデフォルトのコンストラクターが使用されます。 move コンストラクターを明示的に呼び出すには、次のように std::move を使用できます。

<code class="cpp">X z( std::move(X("test")) );</code>

以上が一時オブジェクトからオブジェクトを作成するときに C 11 Move コンストラクターが呼び出されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。