関数の戻り値でオブジェクトを初期化するときにコピーコンストラクターが呼び出されない

クリスロン

次のコードについて考えてみます。

#include <iostream>

using namespace std;

class A
{
    public:
        int a;
        A(): a(5)
        {
           cout << "Constructor\n";
        }
        A(const A &b)
        {
            a = b.a;
            cout << "Copy Constructor\n";
        }
        A fun(A a)
        {
            return a;
        }
};

int main()
{
    A a, c;
    A b = a.fun(c);
    return 0;
}

上記のコードの出力は次のとおりg++ file.cppです。

Constructor
Constructor
Copy Constructor
Copy Constructor

上記のコードの出力は次のとおりg++ -fno-elide-constructors file.cppです。

Constructor
Constructor
Copy Constructor
Copy Constructor
Copy Constructor

私は戻り値の最適化を知っています。私の質問は、コピーコンストラクターのどの呼び出しが省略されているかです(返されるときの一時オブジェクトまたは返されたオブジェクトがbにコピーされます)?

省略されたコピーコンストラクターがbの作成に使用されるものである場合、bはどのように作成されますか(この場合もコンストラクター呼び出しがないため)?

行を置き換えて、最初のメソッドまたは2番目のメソッドを使用A b = a.fun(c);a.fun(c)てコンパイルすると、コピーコンストラクターも2回呼び出されます。したがって、前の段落で説明したケースで、一時オブジェクトのコピーコンストラクターが省略されている場合、なぜこの場合は省略されないのでしょうか。

IdeaHat
#include <iostream>

using namespace std;

class A
{
public:
    int a;
    A(): a(5)
    {
        cout << "Constructing: " << (void *)this << std::endl;
    }
    A(const A &b)
    {
        a = b.a;
        cout << "Copy Constructor: " << (void *)this << " from " << (void *)&b << std::endl;
    }
    A fun(A a)
    {
        return a;
    }
};

int main()
{

    A a, c;
    A b = a.fun(c);

    std::cout << "a:" << (void *)&a << std::endl <<
              "b:" << (void *)&b << std::endl <<
              "c:" << (void *)&c << std::endl;
    return 0;
}

収量:

Constructing: 0x7fffbb377220
Constructing: 0x7fffbb377210
Copy Constructor: 0x7fffbb377230 from 0x7fffbb377210
Copy Constructor: 0x7fffbb377200 from 0x7fffbb377230
a:0x7fffbb377220
b:0x7fffbb377200
c:0x7fffbb377210

したがって、中間体(関数の引数)構築しa、構築しc、コピーしてcから、中間a体をに直接bコピーし、通常のaの戻り中間体へのコピーをスキップします。これは、値を渡すとさらによく示されます(に変更A fun(const A& a)

Constructing: 0x7fff8e9642b0
Constructing: 0x7fff8e9642a0
Copy Constructor: 0x7fff8e964290 from 0x7fff8e9642a0
a:0x7fff8e9642b0
b:0x7fff8e964290
c:0x7fff8e9642a0

bがfunに渡されていないにもかかわらず、aが構築され、cが構築され、cがbに直接コピーされます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

C ++でコピーコンストラクターが呼び出されるのはいつですか?オブジェクトを別のオブジェクトに割り当てるときに呼び出されませんか?

分類Dev

コンストラクターまたはinitブロックから呼び出されたオーバーライドされた抽象関数で変数を初期化するときに変数が正しく初期化されない

分類Dev

constオブジェクトでstd :: moveを呼び出すと、別のオブジェクトに渡されたときにコピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

クラスのオブジェクトに整数値を割り当てるときに、パラメーター化されたコンストラクターが呼び出されるのはなぜですか?

分類Dev

コンストラクターが明示的に呼び出されたときに、戻り値の型がないのに一時オブジェクトを返すのはなぜですか?

分類Dev

そのクラスのオブジェクトが作成されたときにコンストラクターがメモリを取得する外部で関数がクリアされていますか。関数が呼び出されていません

分類Dev

ブレース付き初期化リストで初期化されたオブジェクトを返すときに、コンストラクターとデストラクタの呼び出しのペアが1つ保証されますか?

分類Dev

オブジェクトをパラメーターとして渡すときに、デストラクタが呼び出されているのにコンストラクションが呼び出されていないのはなぜですか?

分類Dev

関数が戻ったときにコピーコンストラクターが呼び出されないのはなぜですか?

分類Dev

一時的な戻りオブジェクトがすぐに別のオブジェクトに割り当てられると、コピーコンストラクタが呼び出されますか

分類Dev

オブジェクトの初期化がコピーコンストラクターを呼び出すのはなぜですか?

分類Dev

現在の標準では、完全なオブジェクトの初期化で例外がスローされたときに、サブオブジェクトのデストラクタを呼び出すことが保証されていますか?

分類Dev

クラスの作成時にJavaコンストラクターが呼び出されますか?オブジェクトが作成されていない場合、「コンストラクターを特定の型に適用できません」エラー

分類Dev

パラメータをコピーすると、削除されたコンストラクタが呼び出されるべきでないときにそのコンストラクタが呼び出されます

分類Dev

値によって関数に渡されたときと別のコンストラクターに値によって渡されたときのコンストラクターの呼び出しに違いがあるのはなぜですか?

分類Dev

参照渡しオブジェクトが関数内の変数の代わりに使用される場合、コピーコンストラクターを呼び出しますか?

分類Dev

NinjectがLazy <T>オブジェクトを注入するときに呼び出されるLazy <T>コンストラクターとは何ですか?

分類Dev

NinjectがLazy <T>オブジェクトを注入するときに呼び出されるLazy <T>コンストラクターとは何ですか?

分類Dev

コピーの初期化:コピーの省略がオフになっているのに、移動またはコピーコンストラクターが呼び出されなかったのはなぜですか?

分類Dev

オブジェクトは、そのメンバー関数を呼び出す前に初期化されることが保証されていますか?

分類Dev

オブジェクトがインスタンス化されたときに親コンストラクターを呼び出す方法は?

分類Dev

C ++オブジェクトのインスタンス化-空の括弧を使用してオブジェクトがインスタンス化されたときに呼び出されるコンストラクター

分類Dev

C ++で作成済みのオブジェクトに実際にコピーしているのに、コピーコンストラクターが呼び出されるのはなぜですか?

分類Dev

C ++で基本クラスへのポインターが与えられたときに、派生クラスオブジェクトのオーバーロードされた関数が呼び出されないのはなぜですか?

分類Dev

Javaで配列を作成するときにオブジェクトコンストラクターが呼び出されますか?

分類Dev

テストコンポーネントのサブジェクトでnext()を呼び出すときに、AngularJasmineスパイが呼び出されない

分類Dev

テストコンポーネントのサブジェクトでnext()を呼び出すときに、AngularJasmineスパイが呼び出されない

分類Dev

引数リストのクラスオブジェクトを別のコンピューターに渡し、そのコンピューターで関数を呼び出すにはどうすればよいですか?

分類Dev

オブジェクトがメンバー関数にバインドされているときに、std :: functionがデストラクタを呼び出すのはなぜですか?

Related 関連記事

  1. 1

    C ++でコピーコンストラクターが呼び出されるのはいつですか?オブジェクトを別のオブジェクトに割り当てるときに呼び出されませんか?

  2. 2

    コンストラクターまたはinitブロックから呼び出されたオーバーライドされた抽象関数で変数を初期化するときに変数が正しく初期化されない

  3. 3

    constオブジェクトでstd :: moveを呼び出すと、別のオブジェクトに渡されたときにコピーコンストラクターが呼び出されるのはなぜですか?

  4. 4

    クラスのオブジェクトに整数値を割り当てるときに、パラメーター化されたコンストラクターが呼び出されるのはなぜですか?

  5. 5

    コンストラクターが明示的に呼び出されたときに、戻り値の型がないのに一時オブジェクトを返すのはなぜですか?

  6. 6

    そのクラスのオブジェクトが作成されたときにコンストラクターがメモリを取得する外部で関数がクリアされていますか。関数が呼び出されていません

  7. 7

    ブレース付き初期化リストで初期化されたオブジェクトを返すときに、コンストラクターとデストラクタの呼び出しのペアが1つ保証されますか?

  8. 8

    オブジェクトをパラメーターとして渡すときに、デストラクタが呼び出されているのにコンストラクションが呼び出されていないのはなぜですか?

  9. 9

    関数が戻ったときにコピーコンストラクターが呼び出されないのはなぜですか?

  10. 10

    一時的な戻りオブジェクトがすぐに別のオブジェクトに割り当てられると、コピーコンストラクタが呼び出されますか

  11. 11

    オブジェクトの初期化がコピーコンストラクターを呼び出すのはなぜですか?

  12. 12

    現在の標準では、完全なオブジェクトの初期化で例外がスローされたときに、サブオブジェクトのデストラクタを呼び出すことが保証されていますか?

  13. 13

    クラスの作成時にJavaコンストラクターが呼び出されますか?オブジェクトが作成されていない場合、「コンストラクターを特定の型に適用できません」エラー

  14. 14

    パラメータをコピーすると、削除されたコンストラクタが呼び出されるべきでないときにそのコンストラクタが呼び出されます

  15. 15

    値によって関数に渡されたときと別のコンストラクターに値によって渡されたときのコンストラクターの呼び出しに違いがあるのはなぜですか?

  16. 16

    参照渡しオブジェクトが関数内の変数の代わりに使用される場合、コピーコンストラクターを呼び出しますか?

  17. 17

    NinjectがLazy <T>オブジェクトを注入するときに呼び出されるLazy <T>コンストラクターとは何ですか?

  18. 18

    NinjectがLazy <T>オブジェクトを注入するときに呼び出されるLazy <T>コンストラクターとは何ですか?

  19. 19

    コピーの初期化:コピーの省略がオフになっているのに、移動またはコピーコンストラクターが呼び出されなかったのはなぜですか?

  20. 20

    オブジェクトは、そのメンバー関数を呼び出す前に初期化されることが保証されていますか?

  21. 21

    オブジェクトがインスタンス化されたときに親コンストラクターを呼び出す方法は?

  22. 22

    C ++オブジェクトのインスタンス化-空の括弧を使用してオブジェクトがインスタンス化されたときに呼び出されるコンストラクター

  23. 23

    C ++で作成済みのオブジェクトに実際にコピーしているのに、コピーコンストラクターが呼び出されるのはなぜですか?

  24. 24

    C ++で基本クラスへのポインターが与えられたときに、派生クラスオブジェクトのオーバーロードされた関数が呼び出されないのはなぜですか?

  25. 25

    Javaで配列を作成するときにオブジェクトコンストラクターが呼び出されますか?

  26. 26

    テストコンポーネントのサブジェクトでnext()を呼び出すときに、AngularJasmineスパイが呼び出されない

  27. 27

    テストコンポーネントのサブジェクトでnext()を呼び出すときに、AngularJasmineスパイが呼び出されない

  28. 28

    引数リストのクラスオブジェクトを別のコンピューターに渡し、そのコンピューターで関数を呼び出すにはどうすればよいですか?

  29. 29

    オブジェクトがメンバー関数にバインドされているときに、std :: functionがデストラクタを呼び出すのはなぜですか?

ホットタグ

アーカイブ