9

Prima di C++ 11, possiamo eseguire l'inizializzazione della copia scrivendo qualcosa come A a = 1; che è più o meno equivalente a A a = A(1);. Cioè, un temporaneo viene prima creato e quindi viene invocato un copy ctor. Indipendentemente dall'elisione della copia, questa deve essere concettualmente e il copyctor deve essere accessibile.L'inizializzazione dell'elenco di copia invoca concettualmente il copy ctor?

Con l'inizializzazione dell'elenco in C++ 11, è possibile eseguire l'inizializzazione dell'elenco di copie scrivendo A a = {1, 2};. A mio parere, questo dovrebbe essere più o meno equivalente a A a = A(1, 2);. Tuttavia, in GCC e clang, A a = {1, 2} compila anche quando il copy and move ctor non è accessibile (dichiarandolo come privato). Ancora, A a = 1; non si compila su GCC o clang se il corrispondente copia/spostamento è inaccessibile. Quindi, A a = {1, 2}; sembra più o meno equivalente a A a{1, 2}; che è l'inizializzazione dell'elenco diretto. La differenza tra questa e l'inizializzazione della lista diretta reale è che A a = {1, 2}; non viene compilato se il ctor che prende due int è esplicito. In questo aspetto, A a = {1, 2}; ricorda l'inizializzazione della copia.

Quindi, la mia domanda è: qual è la semantica esatta di espressioni come A a = {1, 2}; concettualmente? Con concettualmente, copia elision non rimanere nel modo.

+2

Hai spiegato tutto te stesso nella domanda. L'inizializzazione dell'elenco di copie è uguale all'inizializzazione dell'elenco diretto, tranne che il primo non considera i costruttori espliciti. Né richiede un costruttore di copia accessibile. – Praetorian

+0

@Praetorian Questo non sembra esattamente questo. Vedi il mio commento alla risposta di Columbo. – Lingxi

risposta

9

Lo standard lo descrive piuttosto bene; [Dcl.init.list]/3:

List-inizializzazione di un oggetto o di riferimento di tipo T è definito come segue:

  • [...]
  • Altrimenti, se T è un tipo di classe, i costruttori sono considerati. I costruttori applicabili sono enumerati e il migliore viene scelto tramite la risoluzione di sovraccarico (13.3, 13.3.1.7). Se per convertire uno qualsiasi degli argomenti è richiesta una restringente conversione (vedi sotto), il programma è mal formato.

[over.match.list] (enfasi mia):

Quando gli oggetti di tipo non-aggregato classe T sono elenco inizializzata (8.5.4), la risoluzione di sovraccarico seleziona il costruzione in due fasi:

  • Inizialmente, le funzioni candidate sono i costruttori inizializzatore-list (8.5.4) della classe T e la lista degli argomenti con sist di l'elenco di inizializzazione come argomento singolo.

  • Se non viene trovato nessun costruttore di inizializzazione-list praticabile, risoluzione di sovraccarico viene eseguita di nuovo, dove le funzioni candidati sono tutti i costruttori della classe T e la lista degli argomenti è costituito dai elementi della lista di inizializzazione.

Se la lista di inizializzazione non ha elementi e T ha un costruttore di default, la prima fase è omessa.
Nell'inizializzazione elenco di copia, se viene scelto un costruttore , l'inizializzazione non è corretta.

Quindi, se nessuno di inizializzazione-list costruttore si trova (come nel tuo caso), gli elementi della lista di inizializzazione costituiscono gli argomenti per la chiamata al costruttore.
Infatti, la differenza solo di inizializzazione di elenchi diretti e inizializzazione di elenchi di copie è coperta dall'ultima frase in grassetto.

Questo è uno dei vantaggi dell'inizializzazione delle liste: non è necessaria la presenza di una funzione membro speciale che non verrà comunque utilizzata.

+0

Quindi, come spiegare l'inizializzazione della lista di copia nel contesto della chiamata di funzione pass-by-value, ad es., F ({1, 2}); '. Su GCC e clang, questo richiede che il copy/move ctor sia accessibile. Altrimenti, questo programma non viene compilato. – Lingxi

+3

@Lingxi [** Realmente? **] (http://coliru.stacked-crooked.com/a/d85bfae98f38bea3) – Columbo

+0

L'ho testato sul compilatore online incorporato di cppreference.com. Ad esempio, potresti trovarlo nella parte inferiore di http://en.cppreference.com/w/cpp/language/explicit – Lingxi