0

Marshall Cline の C++ FAQ を読んでいます。

現在、ポイント 10.5 のコードをいじっています。

私はこれを持っています:

class Fred
{
public:
  Fred();
  Fred(int x, int y)
  {
    std::cout << "Fred with two ints\n" << std::endl;
  };
};

int main()
{
  std::vector<Fred>(3, Fred(4,5));
  return 0;
}

「Fred with two ints」が 3 回印刷されることを期待していましたが、1 回しか印刷されていません。それはなぜですか - 3回呼び出されていないのですか?

4

2 に答える 2

6

vectorこれは、呼び出しているコンストラクターの署名です。

vector( size_type _Count, const Type& _Val, const Allocator& _Alloc = Allocator() );

Fred(4,5)定義済みのコンストラクターを 1 回呼び出すと、作成されたインスタンスが参照によってvector<Fred>コンストラクターに渡されます。次に、それ [作成されたインスタンス] がベクターに 3 回コピーされます。コピー操作は、(既定の) コピー コンストラクターを使用して実行されます。したがって、コンストラクターは複数回呼び出されません。

于 2012-08-18T11:39:16.077 に答える
2

Fred(4,5) を記述するときに、ユーザー定義のコンストラクターを 1 回呼び出しています。これはベクターのコンストラクターに渡され、3 つの Fred に 3 回コピーされます。これは、デフォルトまたはカスタム コンストラクターではなく、コピー コンストラクターを使用します。独自のコピー コンストラクターを作成しない場合は、代入操作と同様に暗黙的に追加されます。以下に、舞台裏で何が追加されているかを示すために、コピー コンストラクターと代入操作を追加しました。

class Fred
{
public:
  Fred();  // default constructor
  Fred(int x, int y)  // custom constructor
  {
    std::cout << "Fred with two ints\n" << std::endl;
  };
  Fred(const Fred&); // copy constructor
  Fred& operator=(const Fred&);  // assignment operator overload
};

コピー コンストラクター: Fred(const Fred&); ベクトル コンストラクターが Fred を含まれている 3 つの Fred にコピーするときに呼び出されるものです。自分で実装すると、3 回呼び出されることがわかります。完全なデモンストレーションは次のとおりです。

#include <iostream>
#include <vector>
using namespace std;

class Fred
{
private:
    int x,y;

public:
    Fred()  // default constructor
    {
        cout << "Fred's default constructor\n";
    }
    Fred(int x, int y)  // custom constructor
    {
        cout << "Fred's custom constructor\n" << std::endl;
    };
    Fred(const Fred& rhs)   // copy constructor -- NOTE rhs stands for "right-hand-side"
        :x(rhs.x),y(rhs.y)
    {
        cout << "Fred's copy constructor\n";
    }
    Fred& operator=(const Fred& rhs)  // assignment operator overload
    {
        if(&rhs != this)
        { 
            cout << "Fred's assignment overload\n";
            x = rhs.x;
            y = rhs.y;
        }
        return *this;
    }
};

int main(int argc, char** argv)
{
    Fred fred;  // calls default constructor
    vector<Fred> myFreds(3,Fred(4,5));  // calls custom constructor, then copy constructor 3 times.
    fred = myFreds[0]; // calls assignment overload

    return 0;
}

出力:

Fred のデフォルト コンストラクタ
Fred のカスタム コンストラクタ
Fred のコピー コンストラクタ
Fred のコピー コンストラクタ
Fred のコピー コンストラクタ
Fred の代入オーバーロード

コピー コンストラクターと代入オーバーロードを無効にすると、それらを使用しようとするとエラーが発生します。C++11 を使用している場合、上記のように宣言して無効にできる場合は、その後に = delete; を続けます。

Fred(const Fred&) = delete;

C++11 を使用しない場合は、非公開で宣言することで効果的に無効にすることができます。

private:
Fred(const Fred&);  // NOTE: Don't define this function.

無効にすると、無効になっている関数にアクセスしようとするため、プログラムがコンパイルされなくなることがわかります。これらを自分で定義しないことで暗黙的に追加できるようにしたため、コンパイルされただけです。

于 2012-08-18T12:01:45.077 に答える