Condividi tramite


Costruttori di copia e operatori di assegnazione di copia (C++)

Nota

A partire da C++11, nel linguaggio sono supportati due tipi di assegnazione: assegnazione di copia e assegnazione di spostamento. In questo articolo per "assegnazione" si intente assegnazione di copia, se non indicato diversamente in modo esplicito. Per informazioni sull'assegnazione di spostamento, vedere Move Constructors and Move Assignment Operators (C++).

Le operazioni di assegnazione e di inizializzazione comportano entrambe la copia degli oggetti.

  • Assegnazione: quando il valore di un oggetto viene assegnato a un altro oggetto, il primo oggetto viene copiato nel secondo oggetto. Questo codice copia quindi il valore di b in a:

    Point a, b;
    ...
    a = b;
    
  • Inizializzazione: l'inizializzazione si verifica quando si dichiara un nuovo oggetto, quando si passano argomenti di funzione per valore o quando si restituisce per valore da una funzione.

È possibile definire la semantica di "copia" per gli oggetti di tipo classe. Si consideri ad esempio questo codice:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

Il codice precedente potrebbe significare "copiare il contenuto di FILE1. DaT a FILE2. DAT" o potrebbe significare "ignorare FILE2. DAT e creare b un secondo handle per FILE1.DAT." È necessario associare la semantica di copia appropriata a ogni classe, come indicato di seguito:

  • Usare un operatore operator= di assegnazione che restituisce un riferimento al tipo di classe e accetta un parametro passato per const riferimento, ad esempio ClassName& operator=(const ClassName& x);.

  • Usare il costruttore di copia.

Se non si dichiara un costruttore di copia, il compilatore genera automaticamente un costruttore di copia a livello di membro. Analogamente, se non si dichiara un operatore di assegnazione di copia, il compilatore genera automaticamente un operatore di assegnazione di copia a livello di membro. La dichiarazione di un costruttore di copia non elimina l'operatore di assegnazione di copia generato dal compilatore e viceversa. Se si implementa una delle due, è consigliabile implementare anche l'altra. Quando si implementano entrambi, il significato del codice è chiaro.

Il costruttore di copia accetta un argomento di tipo ClassName&, dove ClassName è il nome della classe . Ad esempio:

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Nota

Rendere il tipo dell'argomento const ClassName& del costruttore di copia quando possibile. Ciò impedisce al costruttore di copia di modificare accidentalmente l'oggetto copiato. Consente anche di copiare da const oggetti.

Costruttori di copia generati dal compilatore

I costruttori di copia generati dal compilatore, ad esempio i costruttori di copia definiti dall'utente, hanno un singolo argomento di tipo "reference to class-name". Un'eccezione è quando tutte le classi di base e le classi membro hanno costruttori di copia dichiarati come accettando un singolo argomento di tipo const class-name&. In questo caso, anche constl'argomento del costruttore di copia generato dal compilatore è .

Quando il tipo di argomento per il costruttore di copia non constè , l'inizializzazione copiando un const oggetto genera un errore. Il contrario non è true: se l'argomento è const, è possibile inizializzare copiando un oggetto che non constè .

Gli operatori di assegnazione generati dal compilatore seguono lo stesso modello per const. Accettano un singolo argomento di tipo ClassName& , a meno che gli operatori di assegnazione in tutte le classi base e membro non prendano argomenti di tipo const ClassName&. In questo caso, l'operatore di assegnazione generato per la classe accetta un const argomento.

Nota

Quando le classi di base virtuali vengono inizializzate dai costruttori di copia, generate dal compilatore o definite dall'utente, vengono inizializzate una sola volta: nel momento in cui vengono costruite.

Le implicazioni sono simili al costruttore di copia. Quando il tipo di argomento non constè , l'assegnazione da un const oggetto genera un errore. Il contrario non è true: se un const valore viene assegnato a un valore diverso da const, l'assegnazione ha esito positivo.

Per altre informazioni sugli operatori di assegnazione di overload, vedere Assegnazione.