2015-04-20 8 views
24

È questa classe:Una classe con copy-constructor cancellato è banalmente copiabile?

class A { 
    public: 
    A() = default; 
    A(const A&) = delete; 
}; 

banalmente copiabile? (Almeno clang sembra pensarla così (live))

In particolare, sarebbe

A a,b; 
std::memcpy(&a, &b, sizeof(A)); 

invocare un comportamento indefinito?

Contesto: This answer [eliminato perché dimostrato errato] più l'albero dei commenti.

+0

Perché pensi che la memcpy si comporti diversamente se il costruttore di copie non è stato cancellato? – iheanyi

+5

@iheanyi: Perché ci sono delle regole su ciò che puoi e non puoi fare con lo storage che supporta un oggetto. –

+0

@LightningRacisinObrit No, non c'è. Posso fare tutto ciò che voglio con esso. – iheanyi

risposta

24

Aggiornamento: La risoluzione proposta di CWG 1734, attualmente in stato di "pronto", modificherebbe [class]/p6 per leggere:

Una classe banalmente copiabile è una classe:

  • dove ogni costruttore di copia, costruttore di movimento, operatore di assegnazione copia e operatore di spostamento (12.8 [class.copy], 13.5.3 [over.ass]) è cancellato o banale,
  • che ha almeno un costruttore di copia non cancellato, costruttore di movimento, operatore di assegnazione copia o operatore di spostamento, e
  • con un distruttore banale, non cancellato (12.4 [class.dtor]).

Questo rende le classi come

struct B { 
    B() = default; 
    B(const B&) = delete; 
    B& operator=(const B&) = delete; 
}; 
non è più banalmente

copiabile. (Classi di questo tipo includono primitive di sincronizzazione come std::atomic<T> e std::mutex.)

Tuttavia, il A nel PO ha una implicitamente dichiarata, non cancellato copia operatore di assegnamento che è banale, così rimane banalmente copiabile.

La risposta originale per la situazione pre-CWG1734 è conservata sotto per riferimento.


Sì, un po 'controintuitivamente, è banalmente copiabile. [Class]/p6:

Un banalmente classe copiabile è una classe che:

  • non ci sono costruttori non banali copia (12,8),
  • non ha costruttori mossa non banali (12.8),
  • non ha operatori non banali assegnazione copia (13.5.3, 12.8),
  • ha nessun operatori di assegnazione mossa non banali (13.5.3, 12.8), e
  • ha un distruttore banale (12.4).

[class.copy]/p12:

Una copia/spostamento costruttore per la classe X è banale, se non è fornito dall'utente, la sua parametro di tipo-list è equivalente al parametro di tipo-list di una dichiarazione implicita, e se

  • classe X non ha alcuna fu virtuale nctions (10.3) e nessuna classe base virtuale (10.1), e
  • la classe X non ha membri di dati non statici di tipo volatile e
  • il costruttore selezionato per copiare/spostare ogni sottobase di classe di base diretta è banale e
  • per ogni membro di dati non statici di X che è di tipo classe (o matrice di esso), il costruttore selezionato per copiare/spostare quel membro è banale;

Analogamente ([class.copy]/p25):

Una copia/spostamento operatore di assegnazione per la classe X è banale se non è , la sua parametro di tipo fornito dall'utente -list è equivalente al parametro di tipo-list di una dichiarazione implicita, e se

  • classe X non ha funzioni virtuali (10.3) e senza classi base virtuali (10.1), e
  • classe X non ha membri dati non statici della volatili qualificato tipo, e
  • l'operatore di assegnazione selezionato da copiare/spostare ogni diretto subobject di classe base è banale e
  • per ogni membro di dati non statici di X che è di tipo classe (o matrice di esso), l'operatore di assegnazione selezionato per copiare/spostare quel membro è banale;

[class.dtor]/p5:

Un distruttore è banale se non è fornita dall'utente e se:

  • il distruttore non è virtual,
  • tutte le classi di base dirette della sua classe hanno distruttori banali e
  • per tutte le unità non statiche i membri di dati della sua classe che sono di tipo classe (o array di essi), ciascuna di queste classi ha un distruttore banale .

[dcl.fct.def.predefinita]/p5:

Una funzione viene fornito dall'utente se è user-dichiarata e non esplicitamente in default o cancellato la sua prima dichiarazione.

Infatti, questo è stato a source of problems for the committee itself, perché sotto l'attuale definizione atomic<T> (insieme con mutex e variabili di condizione) sarebbe banalmente copiabile. (E ovviamente, consentire a qualcuno di fare lo atomic o uno atomic o un mutex senza invocare UB sarebbe ... diciamo solo seriamente problematico.) Vedi anche N4460.

+0

Heh, hai già coperto più di quanto ho fatto nel momento in cui ho risposto. Bella scoperta, questo potrebbe significare che anche se è attualmente banalmente copiabile, potrebbe non rimanere banalmente copiabile. – hvd

+0

@hvd L'attuale proposta di risoluzione del problema LWG è fondamentalmente un magico incantesimo ("non importa quale sia il linguaggio principale, questo non è banalmente copiato !!!"). C'è un documento nel mailing pre-Lenexa che discute su vari modi possibili per risolvere questo problema. –

+0

Sembra che la correzione corretta sia "HA un banale costruttore di copie o un banale costruttore di mosse che non viene cancellato E HA un banale compito di copia-assegnazione o di spostamento-incarico che non è cancellato". Se c'è una copia valida che è anche banale, allora la copia banale è valida. Non fa differenza che potrebbe esserci anche una copia più elaborata. –

Problemi correlati