Was ist der Unterschied zwischen Zuweisungsoperator und Kopierkonstruktor?

105

Ich verstehe den Unterschied zwischen Zuweisungskonstruktor und Kopierkonstruktor in C ++ nicht. Es ist so:

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

// The copy constructor
A a = b;

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

// Is it right?

Ich möchte wissen, wie der Speicher des Zuweisungskonstruktors und des Kopierkonstruktors zugewiesen wird.

alan.chen
quelle
2
Hast du ein gutes C ++ - Buch ?
sbi
verwandte FAQ
Fredoverflow

Antworten:

160

Ein Kopierkonstruktor wird verwendet, um ein zuvor nicht initialisiertes Objekt aus den Daten eines anderen Objekts zu initialisieren .

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

Beispielsweise:

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

Ein Zuweisungsoperator wird verwendet, um die Daten eines zuvor initialisierten Objekts durch die Daten eines anderen Objekts zu ersetzen .

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

Beispielsweise:

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

Sie könnten die Kopierkonstruktion durch die Standardkonstruktion plus Zuweisung ersetzen, dies wäre jedoch weniger effizient.

(Als Randnotiz: Meine obigen Implementierungen sind genau die, die der Compiler Ihnen kostenlos gewährt. Daher ist es nicht sinnvoll, sie manuell zu implementieren. Wenn Sie eine dieser beiden Implementierungen haben, ist es wahrscheinlich, dass Sie eine Ressource manuell verwalten. In diesem Fall benötigen Sie gemäß der Dreierregel höchstwahrscheinlich auch den anderen plus einen Destruktor.)

sbi
quelle
4
Nur eine Anmerkung: Heutzutage (ab C ++ 11) können sie explizit mit voreingestellt werden =default;.
Deduplikator
2
@Deduplicator Es ist auch wichtig zu erwähnen, dass Sie bei der Einhaltung von Klassifikationen, die triviale Konstruktoren erfordern, diese dort verwenden müssen = default , wo ein Standard-Ctor benötigt wird: Die einfache Implementierung eines leeren Körpers selbst zählt immer noch als benutzerdefinierter Ctor und somit (auf einer Standardese-Ebene) ) ist nicht trivial und disqualifiziert den Typ von Klassifikationen, die einen trivialen ctor erfordern.
underscore_d
@sbi Kann ich sagen, dass für den Fall, dass der Kopierkonstruktor nicht verwendet wird und stattdessen der Zuweisungsoperator verwendet wird, das Objekt zuerst erstellt wird, indem der Konstruktor entweder mit Argumenten oder ohne Argumente aufgerufen wird. Anschließend wird der Zuweisungsoperator verwendet und neue Werte werden basierend auf RHS zugewiesen. Wenn der Kopierkonstruktor verwendet wird, wird immer noch derselbe Konstruktor aufgerufen, die für die Initialisierung verwendeten Werte stammen jedoch von einem anderen Objekt.
Rajesh
@ Rajesh: Ich bin verwirrt über das, was du fragst, und mein Gefühl ist, dass du auch verwirrt bist. :)Versuchen Sie noch einmal zu erklären, wovon Sie sprechen?
sbi
1
@ CătălinaSîrbu: Du könntest. Sie sind zwei unabhängige Funktionen.
sbi
41

Der Unterschied zwischen dem Kopierkonstruktor und dem Zuweisungsoperator führt bei neuen Programmierern zu großer Verwirrung, ist aber nicht allzu schwierig. Zusammenfassend:

  • Wenn vor dem Kopieren ein neues Objekt erstellt werden muss, wird der Kopierkonstruktor verwendet.
  • Wenn vor dem Kopieren kein neues Objekt erstellt werden muss, wird der Zuweisungsoperator verwendet.

Beispiel für Zuweisungsoperator:

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

Beispiel für einen Kopierkonstruktor:

Base obj1(5);
Base obj2 = obj1; //calls copy constructor
Arun
quelle
Wäre es fair zu sagen, dass ein Zuweisungsoperator die Zerstörung eines alten Objekts effektiv mit der Erstellung eines neuen Objekts kombiniert, jedoch mit der Maßgabe, dass (1) wenn einer der Schritte zur Zerstörung des alten Objekts durch rückgängig gemacht würde Bei einem der Schritte beim Aufbau des neuen können beide Schritte weggelassen werden. (2) Zuweisungsoperatoren sollten keine schlechten Dinge tun, wenn ein Objekt sich selbst zugewiesen wird.
Supercat
Warum tun vector <A> v3und dann v3 = v2 (wo v2ist ein zuvor deklariertes und enthaltendes Element vector<A>) den AKopierkonstruktor meines expliziten stattdessen aufrufen operator=? Ich hatte erwartet operator=, anstelle von angerufen zu werden, copy constructorda mein v3Objekt bereits zu dem Zeitpunkt deklariert war, an dem ich den Auftrag ausgeführt habe
Cătălina Sîrbu,
19

Die erste ist die Kopierinitialisierung, die zweite ist nur die Zuweisung. Es gibt keinen Zuweisungskonstruktor.

A aa=bb;

verwendet den vom Compiler generierten Kopierkonstruktor.

A cc;
cc=aa;

verwendet den Standardkonstruktor zum Konstruieren ccund dann den * Zuweisungsoperator ** ( operator =) für ein bereits vorhandenes Objekt.

Ich möchte wissen, wie Speicher des Zuweisungskonstruktors und des Kopierkonstruktors zugewiesen wird.

IDK, was Sie unter Speicherzuweisung in diesem Fall verstehen. Wenn Sie jedoch sehen möchten, was passiert, können Sie:

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;}
};

Ich empfehle Ihnen auch einen Blick auf:

Warum wird der Kopierkonstruktor anstelle des Konvertierungskonstruktors aufgerufen?

Was ist die Dreierregel?

Luchian Grigore
quelle
5

In einfachen Worten:

Der Kopierkonstruktor wird aufgerufen, wenn aus einem vorhandenen Objekt ein neues Objekt als Kopie des vorhandenen Objekts erstellt wird. Der Zuweisungsoperator wird aufgerufen, wenn einem bereits initialisierten Objekt ein neuer Wert von einem anderen vorhandenen Objekt zugewiesen wird.

Beispiel-

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

Was @Luchian Grigore Said so implementiert ist

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
}

AUSGABE


Standardkonstruktor


Konstruktor kopieren


Standardkonstruktor


Aufgabenverwalter


Mak
quelle
4

Der Unterschied zwischen einem Kopierkonstruktor und einem Zuweisungskonstruktor ist:

  1. Im Falle eines Kopierkonstruktors wird ein neues Objekt erstellt. ( <classname> <o1>=<o2>)
  2. Im Falle eines Zuweisungskonstruktors wird kein Objekt erstellt, dh es wird auf bereits erstellte Objekte angewendet ( <o1>=<o2>).

Und die grundlegenden Funktionen in beiden sind gleich. Sie kopieren die Daten von o2 nach o1 Mitglied für Mitglied.

Nitesh Kumar
quelle
2

Ich möchte noch einen Punkt zu diesem Thema hinzufügen. "Die Operatorfunktion des Zuweisungsoperators sollte nur als Mitgliedsfunktion der Klasse geschrieben werden." Wir können es nicht als Freundfunktion machen, im Gegensatz zu anderen binären oder unären Operatoren.

MD BELAL RASHID
quelle
1

Was Sie zum Kopierkonstruktor hinzufügen sollten:

  • Wenn Sie ein Objekt als Wert übergeben, wird der Kopierkonstruktor verwendet

  • Wenn ein Objekt von einer Funktion nach Wert zurückgegeben wird, wird der Kopierkonstruktor verwendet

  • Beim Initialisieren eines Objekts anhand der Werte eines anderen Objekts (als Beispiel).

Frank Shen
quelle