2

次のコード スニペットを使用して、C++ でオブジェクトを作成する 2 つの方法を比較しています。

#include <iostream>

using std::cout;
using std::endl;

class Foo {
    public:
        Foo() : x(0) { cout << "In Foo constructor." << endl; }
        ~Foo() { cout << "In Foo destructor." << endl; }
        Foo(const Foo&) { cout << "In Foo copy constructor." << endl; }

        // Assignment operator.
        Foo& operator=(const Foo&) {
            cout << "In assignment operator." << endl;
            return *this;
        }

    private:
        int x;
};

int main() {

    cout << "Constructing Foo 1" << endl;
    Foo Foo_1;
    cout << "Constructing Foo 2" << endl;
    Foo Foo_2 = Foo();

    return 0;
}

このコード スニペットの出力は次のとおりです。

  Constructing Foo 1
  In Foo constructor.
  Constructing Foo 2
  In Foo constructor.
  In Foo destructor.
  In Foo destructor.

Visual C++ 2010 (コンパイラ バージョン 16.x) を使用しており、cl /EHsc /W4 test.cpp. . Foo_2_ Foo_2_ なぜそうではないのか、誰かが私に説明できますか。ここで非常に明白な何かが欠けている場合はお詫び申し上げます。

4

3 に答える 3

4

で使用できる初期化には、次の 2 つの形式がありますFoo

Foo f1;
Foo f2 = Foo();

最初のコンストラクターfは、デフォルトのコンストラクターを使用して直接構築します。2 番目は、デフォルトのコンストラクターを使用して type のテンポラリをFoo構築し、そのテンポラリを にコピーしf2ます。後者は、あなたが期待したものとして説明したものです。そして、1 つの追加のルールを除いて、あなたは正しいです: その形式の初期化が有効な場合 (それはここにあります。コピー コンストラクターをプライベートにして、何が起こるかを確認します)、コンパイラーはコピーの構築を「省略」し、f2直接構築することができます。 、最初のバージョンと同じように。それがあなたが見ているものです。コピー コンストラクターを削除するのにコンパイラーは必須ではありませんが、私が最近使用したものはすべて必要です。

于 2012-10-24T17:48:20.663 に答える
1

最初の「今週の達人」の問題は、あなたの質問についてですhttp://www.gotw.ca/gotw/001.htm 特にコンパイラの最適化に関する注意事項です。

于 2012-10-24T18:04:06.520 に答える
1

Foo Foo_2 = Foo();に似ていFoo Foo_2(Foo());ます。コンパイラはこれを行うのに十分スマートであり、代入演算子は呼び出されていません。ところで、代入演算子にバグがあります。オブジェクトをコピーするのではなく、オブジェクトへの参照を返します。

于 2012-10-24T17:42:42.660 に答える