3

コピーコンストラクターが呼び出されたときと代入演算子が呼び出されたときをテストするために、次のプログラムを作成しました。


#include 

class Test
{
public:
    Test() :
        iItem (0)
    {
        std::cout << "This is the default ctor" << std::endl;
    }

    Test (const Test& t) :
        iItem (t.iItem)

    {
        std::cout << "This is the copy ctor" << std::endl;
    }

    ~Test()
    {
        std::cout << "This is the dtor" << std::endl;
    }

    const Test& operator=(const Test& t)
    {
        iItem = t.iItem;    
        std::cout << "This is the assignment operator" << std::endl;
        return *this;
    }

private:
    int iItem;
};

int main()
{
    {
        Test t1;
        Test t2 = t1;
    }
    {
        Test t1;
        Test t2 (t1);
    }
    {
        Test t1;
        Test t2;
        t2 = t1;
    }
}

これにより、次の出力が得られます(わかりやすくするためにempy行を追加しただけです)。

doronw @ DW01:〜$ ./test
これはデフォルトのコンストラクタです
これはコピーコンストラクタです
これはdtorです
これはdtorです

これはデフォルトのコンストラクタです
これはコピーコンストラクタです
これはdtorです
これはdtorです

これはデフォルトのコンストラクタです
これはデフォルトのコンストラクタです
これは代入演算子です
これはdtorです
これはdtorです


2番目と3番目のセットは期待どおりに動作しますが、最初のセットでは、代入演算子が使用されていても、コピーコンストラクターが呼び出されます。

この動作はC++標準の一部ですか、それとも単に賢いコンパイラ最適化ですか(私はgcc 4.4.1を使用しています)

4

3 に答える 3

10

最初のテスト ケースでは代入演算子は使用されません。「コピー初期化」と呼ばれる初期化形式を使用するだけです。コピーの初期化では、オブジェクトの初期化時に明示的なコンストラクターは考慮されません。

struct A {
  A();

  // explicit copy constructor
  explicit A(A const&);

  // explicit constructor
  explicit A(int);

  // non-explicit "converting" constructor
  A(char const*c);
};

A a;
A b = a; // fail
A b1(a); // succeeds, "direct initialization"

A c = 1; // fail, no converting constructor found
A d(1); // succeeds

A e = "hello"; // succeeds, converting constructor used

コピーの初期化は、関数の引数の受け渡しや関数からの戻りのように、明示的に変換を開始しない暗黙の変換に対応する場合に使用されます。

于 2010-01-08T13:45:28.130 に答える
3

C++標準8.5/12

引数の受け渡し、関数の戻り、例外のスロー(15.1)、例外の処理(15.3)、および中括弧で囲まれた初期化子リスト(8.5.1)で発生する初期化は、コピー初期化と呼ばれ、次の形式と同等です。

T x = a;

新しい式(5.3.4)、static_cast式(5.2.9)、関数表記型変換(5.2.3)、およびベースとメンバーの初期化子(12.6.2)で発生する初期化は、直接初期化と呼ばれ、フォーム

T x(a);
于 2010-01-08T13:57:24.463 に答える
2

最初のセットは C++ 標準に従っており、最適化によるものではありません。

C++ 標準のセクション 12.8 ( [class.copy]) には、同様の例が示されています。

class X {
    // ...
public:
    X(int);
    X(const X&, int = 1);
};

X a(1);     // calls X(int);
X b(a, 0);  // calls X(const X&, int);
X c = b;    // calls X(const X&, int);

最後の行は、ケースに一致するものです。

于 2010-01-08T13:50:26.020 に答える