代入演算子とコピーコンストラクタの違いは何ですか?


105

C ++での代入コンストラクターとコピーコンストラクターの違いがわかりません。それはこのようなものです:

class A {
public:
    A() {
        cout << "A::A()" << endl;
    }
};

// The copy constructor
A a = b;

// The assignment constructor
A c;
c = a;

// Is it right?

割り当てコンストラクターとコピーコンストラクターのメモリを割り当てる方法を知りたいですか?


2
あなたは良いC ++の本を持ってますか?
sbi

回答:


160

コピーコンストラクタを初期化するために使用される以前に初期化されていないいくつかの他のオブジェクトのデータからオブジェクトを。

A(const A& rhs) : data_(rhs.data_) {}

例えば:

A aa;
A a = aa;  //copy constructor

代入演算子は、データ交換するために使用される以前に初期化され、いくつかの他のオブジェクトのデータを持つオブジェクト。

A& operator=(const A& rhs) {data_ = rhs.data_; return *this;}

例えば:

A aa;
A a;
a = aa;  // assignment operator

コピー構築をデフォルトの構築と割り当てで置き換えることもできますが、それでは効率が低下します。

(補足として:上記の私の実装は、コンパイラーが無料で許可するものなので、手動で実装することはあまり意味がありません。これら2つのうちの1つがある場合、いくつかのリソースを手動で管理している可能性があります。その場合、3つのルールに従って、もう1つとデストラクターも必要になる可能性が高くなります。)


4
ただ注意:最近(C ++ 11以降)、それらはで明示的にデフォルトにすることができます=default;
デデュプリケータ2014

2
@Deduplicatorまた、重要なコンストラクタを必要とする分類に準拠する場合、デフォルトのctorが必要な場所でそれらを実行する必要がある = defaultことを説明することも重要です。 )は自明ではなく、自明なctorを必要とする分類から型を失格にします。
underscore_d

@sbiコピーコンストラクターが使用されず、代わりに代入演算子が使用される場合、引数付きまたは引数なしのコンストラクターを呼び出すことによってオブジェクトが最初に作成され、次に代入演算子が使用され、RHSに基づいて新しい値が割り当てられると言えるでしょうか。コピーコンストラクターが使用される場合、同じコンストラクターが呼び出されますが、初期化に使用される値は他のオブジェクトからのものです。
ラジェッシュ2018年

@Rajesh:私はあなたが何を求めているのか混乱しています。私の気持ちは、あなたも混乱しているからです。:)あなたが話していることをもう一度説明してみませんか?
sbi 2018年

1
@CătălinaSîrbu:できます。2つの独立した機能です。
sbi

41

コピーコンストラクターと代入演算子の違いは、新しいプログラマーに多くの混乱を引き起こしますが、それほど難しいことではありません。要約:

  • コピーを行う前に新しいオブジェクトを作成する必要がある場合は、コピーコンストラクターを使用します。
  • コピーを行う前に新しいオブジェクトを作成する必要がない場合は、代入演算子が使用されます。

代入演算子の例:

Base obj1(5); //calls Base class constructor
Base obj2; //calls Base class default constructor
obj2 = obj1; //calls assignment operator

コピーコンストラクタの例:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor

割り当て演算子は古いオブジェクトの破棄を新しいオブジェクトの作成と効果的に組み合わせるが、(1)古いオブジェクトの破棄のステップの1つが新しいものの構築のステップの1つ。両方のステップを省略できます。(2)オブジェクトがそれ自体に割り当てられている場合、代入演算子は悪いことをしてはいけません。
スーパーキャット2013

なぜ実行vector <A> v3してからv3 = v2 v2以前に宣言され、要素が含まれている場合vector<A>A代わりに明示的なコピーコンストラクターを呼び出しoperator=ますか?私は期待していたoperator=の代わりに呼ばれるようにcopy constructor私のためにv3オブジェクトがすでに私が割り当てをした時に宣言されました
カタリナSIRBU

19

1つ目はコピーの初期化、2つ目は割り当てです。割り当てコンストラクターなどはありません。

A aa=bb;

コンパイラが生成したコピーコンストラクタを使用します。

A cc;
cc=aa;

デフォルトのコンストラクターを使用してを作成しcc、次にoperator =既存のオブジェクトに*代入演算子**()を使用します。

割り当てコンストラクターとコピーコンストラクターのメモリを割り当てる方法を知りたいですか?

この場合、メモリを割り当てるという意味のIDKですが、何が起こるかを確認したい場合は、次のことができます。

class A
{
public :
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

以下もご覧になることをお勧めします。

変換コンストラクタの代わりにコピーコンストラクタが呼び出されるのはなぜですか?

3つのルールとは何ですか?


5

簡単に言えば、

コピーコンストラクターは、既存のオブジェクトのコピーとして、既存のオブジェクトから新しいオブジェクトが作成されるときに呼び出されます。また、代入演算子は、初期化済みのオブジェクトに別の既存のオブジェクトから新しい値が割り当てられたときに呼び出されます。

例-

t2 = t1;  // calls assignment operator, same as "t2.operator=(t1);"
Test t3 = t1;  // calls copy constructor, same as "Test t3(t1);"

4

@Luchian Grigore Saidがこのように実装されているもの

class A
{
public :
    int a;
    A(){ cout<<"default constructor"<<endl;};
    A(const A& other){ cout<<"copy constructor"<<endl;};
    A& operator = (const A& other){cout <<"assignment operator"<<endl;}
};

void main()
{
    A sampleObj; //Calls default constructor
    sampleObj.a = 10;

    A copyConsObj  = sampleObj; //Initializing calls copy constructor

    A assignOpObj; //Calls default constrcutor
    assignOpObj = sampleObj; //Object Created before so it calls assignment operator
}

出力


デフォルトのコンストラクタ


コピーコンストラクタ


デフォルトのコンストラクタ


代入演算子



4

コピーコンストラクタと割り当てコンストラクタの違いは次のとおりです。

  1. コピーコンストラクタの場合、新しいオブジェクトを作成します。(<classname> <o1>=<o2>
  2. 割り当てコンストラクターの場合、オブジェクトは作成されません。つまり、作成済みのオブジェクト(<o1>=<o2>)に適用されます。

両方の基本的な機能は同じで、o2からo1にメンバーごとにデータをコピーします。


2

このトピックについてもう1つポイントを追加したいと思います。「代入演算子の演算子関数は、クラスのメンバー関数としてのみ記述する必要があります。」他の二項演算子や単項演算子とは異なり、フレンド関数として作成することはできません。


1

コピーコンストラクタについて追加するもの:

  • オブジェクトを値で渡す場合、コピーコンストラクタを使用します

  • オブジェクトが関数から値によって返される場合、コピーコンストラクタを使用します

  • 別のオブジェクトの値を使用してオブジェクトを初期化するとき(例として)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.