Qual è la differenza tra l'operatore di assegnazione e il costruttore di copia?


105

Non capisco la differenza tra il costruttore di assegnazioni e il costruttore di copie in C ++. È così:

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

// The copy constructor
A a = b;

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

// Is it right?

Voglio sapere come allocare la memoria del costruttore dell'assegnazione e del costruttore della copia?



Risposte:


160

Un costruttore di copia viene utilizzato per inizializzare un oggetto precedentemente non inizializzato dai dati di qualche altro oggetto.

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

Per esempio:

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

Un operatore di assegnazione viene utilizzato per sostituire i dati di un oggetto precedentemente inizializzato con i dati di un altro oggetto.

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

Per esempio:

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

Potresti sostituire la costruzione della copia con la costruzione predefinita più l'assegnazione, ma sarebbe meno efficiente.

(Come nota a margine: le mie implementazioni sopra sono esattamente quelle che il compilatore ti concede gratuitamente, quindi non avrebbe molto senso implementarle manualmente. Se hai una di queste due, è probabile che tu stia gestendo manualmente alcune risorse. In tal caso, secondo La regola del tre , molto probabilmente avrai bisogno anche dell'altro più un distruttore.)


4
Solo una nota: al giorno d'oggi (da C ++ 11 in poi), possono essere impostati in modo predefinito con =default;.
Deduplicator

2
@Deduplicator È anche importante ricordare che, quando si aderisce a classificazioni che richiedono costruttori banali, è necessario = default inserirli laddove è necessario un ctor predefinito: semplicemente implementare un corpo vuoto da soli conta ancora come un ctor definito dall'utente e quindi (a livello Standardese ) non è banale e squalifica il tipo dalle classificazioni che richiedono un ctor banale.
underscore_d

@sbi Posso dire che nel caso in cui non venga utilizzato il costruttore di copia e invece viene utilizzato l'operatore di assegnazione, l'oggetto viene creato prima chiamando il costruttore con o senza argomenti, quindi viene utilizzato l'operatore di assegnazione e vengono assegnati nuovi valori in base a RHS. Nel caso in cui venga utilizzato il costruttore di copia, verrà chiamato lo stesso costruttore, ma i valori utilizzati per l'inizializzazione provengono da un altro oggetto.
Rajesh

@Rajesh: Sono confuso su quello che stai chiedendo, e la mia sensazione è che sia perché anche tu sei confuso. :)Proverai di nuovo a spiegare di cosa stai parlando?
sbi

1
@ CătălinaSîrbu: Potresti. Sono due funzioni indipendenti.
sbi

41

La differenza tra il costruttore di copia e l'operatore di assegnazione crea molta confusione per i nuovi programmatori, ma non è poi così difficile. riassumendo:

  • Se è necessario creare un nuovo oggetto prima di poter eseguire la copia, viene utilizzato il costruttore di copia.
  • Se non è necessario creare un nuovo oggetto prima di poter eseguire la copia, viene utilizzato l'operatore di assegnazione.

Esempio di operatore di assegnazione:

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

Esempio per il costruttore di copie:

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

Sarebbe corretto affermare che un operatore di assegnazione combina efficacemente la distruzione di un vecchio oggetto con la creazione di uno nuovo, ma con le condizioni che (1) se uno dei passaggi nella distruzione del vecchio oggetto fosse annullato da uno dei passaggi nella costruzione del nuovo, entrambi i passaggi possono essere omessi; (2) gli operatori di assegnazione non dovrebbero fare cose cattive se un oggetto viene assegnato a se stesso.
supercat

perché fare vector <A> v3e quindi v3 = v2 (dov'è v2un elemento precedentemente dichiarato e contenente elementi vector<A>) chiama il mio Acostruttore di copia esplicito invece del operator=? Mi aspettavo operator=di essere chiamato al posto del copy constructorperché il mio v3oggetto era già stato dichiarato al momento in cui ho svolto l'incarico
Cătălina Sîrbu

19

Il primo è l'inizializzazione della copia, il secondo è solo l'assegnazione. Non esiste un costruttore di assegnazioni.

A aa=bb;

usa il costruttore di copie generato dal compilatore.

A cc;
cc=aa;

usa il costruttore predefinito per costruire cc, quindi l'operatore di assegnazione * ** ( operator =) su un oggetto già esistente.

Voglio sapere come allocare la memoria del costruttore dell'assegnazione e del costruttore della copia?

IDK cosa intendi per allocare memoria in questo caso, ma se vuoi vedere cosa succede, puoi:

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

Ti consiglio anche di dare un'occhiata a:

Perché viene chiamato il costruttore di copia invece del costruttore di conversione?

Qual è la regola del tre?


5

In poche parole,

Il costruttore di copia viene chiamato quando viene creato un nuovo oggetto da un oggetto esistente, come copia dell'oggetto esistente. E l'operatore di assegnazione viene chiamato quando a un oggetto già inizializzato viene assegnato un nuovo valore da un altro oggetto esistente.

Esempio-

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

4

Quello che ha detto @Luchian Grigore è implementato in questo modo

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
}

PRODUZIONE


costruttore predefinito


costruttore di copie


costruttore predefinito


operatore di assegnazione



4

la differenza tra un costruttore di copie e un costruttore di assegnazioni è:

  1. In caso di un costruttore di copia crea un nuovo oggetto. ( <classname> <o1>=<o2>)
  2. In caso di un costruttore di assegnazioni non creerà alcun oggetto, significa che si applica a oggetti già creati ( <o1>=<o2>).

E le funzionalità di base in entrambi sono le stesse, copieranno i dati da o2 a o1 membro per membro.


2

Voglio aggiungere un altro punto su questo argomento. "La funzione operatore di operatore di assegnazione deve essere scritta solo come una funzione membro della classe." Non possiamo farlo come funzione amico a differenza di altri operatori binari o unari.


1

Qualcosa da aggiungere sul costruttore di copie:

  • Quando si passa un oggetto per valore, utilizzerà il costruttore di copia

  • Quando un oggetto viene restituito da una funzione in base al valore, utilizzerà il costruttore di copia

  • Quando si inizializza un oggetto utilizzando i valori di un altro oggetto (come nell'esempio fornito).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.