Condizioni per la generazione automatica dell'operatore di default / copia / sposta ctor e copia / sposta assegnazione?


Risposte:


136

Di seguito, "generato automaticamente" significa "dichiarato implicitamente come predefinito, ma non definito come eliminato". Vi sono situazioni in cui vengono dichiarate le funzioni speciali dei membri, ma definite come eliminate.

  • Il costruttore predefinito viene generato automaticamente se non esiste un costruttore dichiarato dall'utente (§12.1 / 5).
  • Il costruttore di copie viene generato automaticamente se non esiste alcun costruttore di spostamento dichiarato o operatore di assegnazione di spostamento (poiché non sono presenti costruttori di spostamento o operatori di assegnazione di spostamento in C ++ 03, ciò semplifica "sempre" in C ++ 03) ( §12.8 / 8).
  • L'operatore di assegnazione della copia viene generato automaticamente se non vi è alcun costruttore di spostamento dichiarato o operatore di assegnazione di spostamento (§12.8 / 19).
  • Il distruttore viene generato automaticamente se non esiste un distruttore dichiarato dall'utente (§12.4 / 4).

Solo C ++ 11 e versioni successive:

  • Il costruttore di movimenti viene generato automaticamente se non esistono costruttori di copie dichiarati dall'utente, operatori di assegnazione di copie o distruttori e se il costruttore di movimenti generato è valido (§12.8 / 10).
  • L'operatore di assegnazione di spostamenti viene generato automaticamente se non esistono costruttori di copie, operatori di assegnazione di copie o distruttori dichiarati dall'utente e se l'operatore di assegnazione di spostamenti generato è valido (ad esempio se non è necessario assegnare membri costanti) (§12.8 / 21).

9
Conta un distruttore ereditato? Voglio dire, suppongo di avere una classe base con un distruttore virtuale vuoto. Impedisce la creazione di costruttori di mosse in sottoclassi? Se la risposta è sì, sarà di aiuto se definissi un costruttore di mosse nella classe base?
kamilk,

10
Penso che dovresti menzionare forse che avere constmembri nella classe impedirà al costruttore di essere generato automaticamente ...
nonsickick

Fa "Esistono situazioni in cui le funzioni speciali del membro vengono dichiarate, ma definite come eliminate". fai riferimento a dove ad esempio hai membri const o di riferimento in cui lo spostamento sarà impossibile? No, non può essere, perché verrà applicata una copia.
towi,

So che è limitato l'invio di collegamenti ipertestuali in questo forum. Ma è anche un buon articolo - cplusplus.com/articles/y8hv0pDG
bruziuz,

Si noti che, come standard, un costruttore di copia implicitamente predefinito " è deprecato se la classe ha un operatore di assegnazione di copie dichiarato dall'utente o un distruttore dichiarato dall'utente " ( 12.8 Copia e spostamento di oggetti di classe [class.copy] ).
sigy

98

Ho trovato il diagramma di seguito molto utile.

Regole C ++ per costruttori automatici e operatori di assegnazione da Sticky Bits: diventare una regola di Zero Hero


Bellissimo. A cosa si riferisce "indipendente"? Indipendente da cosa?
towi,

8
Copia ctor / incarico sono "indipendenti" l'uno dall'altro. Se ne scrivi solo uno, il compilatore fornirà l'altro. Al contrario, se si fornisce un gestore di spostamento o un'assegnazione di spostamento, il compilatore non fornirà l'altro.
Marco M.,

Mi chiedo qual è il motivo dietro le operazioni di copia sono indipendenti. Le ragioni storiche possono essere? o il fatto che la copia non cambierà il suo target ma lo sposta?
RaGa__M,

@Explorer_N Sì, retrocompatibilità, quindi ragioni storiche. È stata una cattiva scelta progettuale molto tempo fa, quindi ora c'è bisogno di buone pratiche come la "regola dei tre" (definisci tutti e tre o nessuno: copia costruttore, copia operatore di assegnazione e spesso distruttore) per evitare bug difficili da trovare.
atablash,

@MarcoM., Per quanto ho capito, la condizione "Se scrivi ..." include i due casi di impostazione della funzione membro speciale su = delete(ovvio) o = default(meno ovvio per me). Ho ragione?
Enrico Maria De Angelis,

2

Bozza standard C ++ 17 N4659

Per un rapido riferimento incrociato, dai un'occhiata alle sezioni "Dichiarate implicitamente" delle seguenti voci cppreference:

Le stesse informazioni possono ovviamente essere ottenute dallo standard. Ad es. Su bozza standard C ++ 17 N4659 :

15.8.1 "Copia / sposta costruttori" dice per costruttore di copia:

6 Se la definizione della classe non dichiara esplicitamente un costruttore di copie, ne viene dichiarata implicitamente una non esplicita. Se la definizione di classe dichiara un costruttore di spostamento o un operatore di assegnazione di spostamento, il costruttore di copia dichiarato implicitamente viene definito come eliminato; in caso contrario, viene definito come predefinito (11.4). Quest'ultimo caso è obsoleto se la classe ha un operatore di assegnazione della copia dichiarato dall'utente o un distruttore dichiarato dall'utente.

e per costruttore di movimento:

8 Se la definizione di una classe X non dichiara esplicitamente un costruttore di mosse, una non esplicita verrà dichiarata implicitamente come predefinita se e solo se

  • (8.1) - X non ha un costruttore di copie dichiarato dall'utente,

  • (8.2) - X non ha un operatore di assegnazione di copie dichiarato dall'utente,

  • (8.3) - X non ha un operatore di assegnazione di spostamenti dichiarato dall'utente e

  • (8.4) - X non ha un distruttore dichiarato dall'utente.

15.8.2 "Operatore di assegnazione copia / spostamento" dice per assegnazione copia:

2 Se la definizione della classe non dichiara esplicitamente un operatore di assegnazione della copia, ne viene dichiarata implicitamente una. Se la definizione della classe dichiara un costruttore di spostamento o un operatore di assegnazione di spostamenti, l'operatore di assegnazione di copia dichiarato implicitamente viene definito come eliminato; in caso contrario, viene definito come predefinito (11.4). Quest'ultimo caso è obsoleto se la classe ha un costruttore di copia dichiarato dall'utente o un distruttore dichiarato dall'utente.

e per l'assegnazione delle mosse:

4 Se la definizione di una classe X non dichiara esplicitamente un operatore di assegnazione di spostamenti, uno verrà implicitamente dichiarato come predefinito se e solo se

  • (4.1) - X non ha un costruttore di copie dichiarato dall'utente,
  • (4.2) - X non ha un costruttore di movimenti dichiarato dall'utente,
  • (4.3) - X non ha un operatore di assegnazione della copia dichiarato dall'utente e
  • (4.4) - X non ha un distruttore dichiarato dall'utente.

15.4 "Distruttori" lo dice per i distruttori:

4 Se una classe non ha distruttori dichiarati dall'utente, un distruttore viene implicitamente dichiarato predefinito (11.4). Un distruttore dichiarato implicitamente è un membro pubblico in linea della sua classe.

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.