Ho visto default
usato accanto alle dichiarazioni di funzioni in una classe. Che cosa fa?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Ho visto default
usato accanto alle dichiarazioni di funzioni in una classe. Che cosa fa?
class C {
C(const C&) = default;
C(C&&) = default;
C& operator=(const C&) & = default;
C& operator=(C&&) & = default;
virtual ~C() { }
};
Risposte:
È una nuova funzionalità di C ++ 11 .
Significa che si desidera utilizzare la versione generata dal compilatore di quella funzione, quindi non è necessario specificare un corpo.
Puoi anche usare = delete
per specificare che non vuoi che il compilatore generi automaticamente quella funzione.
Con l'introduzione dei costruttori di mosse e degli operatori di assegnazione di mosse, le regole per la generazione di versioni automatiche di costruttori, distruttori e operatori di assegnazione sono diventate piuttosto complesse. Usare = default
e = delete
rendere le cose più facili in quanto non è necessario ricordare le regole: dite semplicemente cosa volete che accada.
= delete
è più forte: significa che è vietata l'utilizzo di tale funzione, sebbene partecipi ancora alla risoluzione del sovraccarico.
Questa è una nuova funzionalità C ++ 0x che dice al compilatore di creare la versione predefinita del rispettivo costruttore o operatore di assegnazione, ovvero quella che esegue semplicemente la copia o sposta l'azione per ciascun membro. Ciò è utile perché il costruttore di spostamento non è sempre generato per impostazione predefinita (ad esempio se si dispone di un distruttore personalizzato), a differenza del costruttore di copie (e allo stesso modo per l'assegnazione), ma se non c'è nulla di non banale da scrivere, è meglio lasciare che il compilatore gestirlo piuttosto che spiegarlo ogni volta.
Si noti inoltre che non verrà generato un costruttore predefinito se si fornisce qualsiasi altro costruttore non predefinito. Se vuoi ancora anche il costruttore predefinito, puoi usare questa sintassi per fare in modo che il compilatore ne faccia uno.
Come altro caso d'uso, ci sono diverse situazioni in cui un costruttore di copie non verrebbe generato implicitamente (ad esempio se si fornisce un costruttore di spostamenti personalizzato). Se desideri ancora la versione predefinita, puoi richiederla con questa sintassi.
Vedere la Sezione 12.8 della norma per i dettagli.
operator new/new[]
, operator delete/delete[]
e le loro sovraccarichi.
È nuovo in C ++ 11, vedi qui . Può essere abbastanza utile se hai definito un costruttore, ma vuoi usare i valori predefiniti per gli altri. Prima di C ++ 11 dovresti definire tutti i costruttori dopo averne definito uno, anche se equivalgono ai valori predefiniti.
Si noti inoltre che in determinate situazioni è impossibile fornire un costruttore predefinito definito dall'utente che si comporti come quello del compilatore sintetizzato sia con l' inizializzazione predefinita che con il valore . default
ti consente di riavere quel comportamento.
Bozza standard C ++ 17 N4659
https://github.com/cplusplus/draft/blob/master/papers/n4659.pdf 11.4.2 "Funzioni esplicitamente predefinite":
1 Una definizione di funzione del modulo:
attribute-specifier-seq opt decl-specifier-seq opt declarator virt-specifier-seq opt = default ;
viene chiamata definizione esplicitamente predefinita. Una funzione che è esplicitamente in default deve
(1.1) - essere una funzione membro speciale,
(1.2) - hanno lo stesso tipo di funzione dichiarata (tranne che per qualificatori di ref eventualmente diversi e salvo che nel caso di un costruttore di copie o di un operatore di assegnazione di copie, il tipo di parametro può essere "riferimento a T non costante", dove T è il nome della classe della funzione membro) come se fosse stato implicitamente dichiarato, e
(1.3) - non ha argomenti predefiniti.
2 Una funzione esplicitamente predefinita che non è definita come eliminata può essere dichiarata constexpr solo se fosse stata dichiarata implicitamente come constexpr. Se una funzione viene esplicitamente impostata sulla prima dichiarazione, viene implicitamente considerata constexpr se la dichiarazione implicita lo fosse.
3 Se una funzione esplicitamente predefinita viene dichiarata con un specificatore noexcept che non produce la stessa specifica di eccezione della dichiarazione implicita (18.4), allora
(3.1) - se la funzione è esplicitamente predefinita sulla sua prima dichiarazione, è definita come eliminata;
(3.2) - in caso contrario, il programma è mal formato.
4 [Esempio:
struct S { constexpr S() = default; // ill-formed: implicit S() is not constexpr S(int a = 0) = default; // ill-formed: default argument void operator=(const S&) = default; // ill-formed: non-matching return type ~ S() noexcept(false) = default; // deleted: exception specification does not match private: int i; // OK: private copy constructor S(S&); }; S::S(S&) = default; // OK: defines copy constructor
- fine esempio]
5 Le funzioni esplicitamente predefinite e le funzioni dichiarate implicitamente sono chiamate collettivamente funzioni predefinite e l'implementazione fornirà loro definizioni implicite (15.1 15.4, 15.8), il che potrebbe significare definirle come cancellate. Una funzione viene fornita dall'utente se viene dichiarata dall'utente e non viene esplicitamente modificata o eliminata nella sua prima dichiarazione. Una funzione fornita dall'utente in modo esplicito (ovvero, esplicitamente in difetto dopo la sua prima dichiarazione) è definita nel punto in cui è esplicitamente predefinita; se tale funzione è implicitamente definita come eliminata, il programma è mal formato. [Nota: la dichiarazione di una funzione come predefinita dopo la sua prima dichiarazione può fornire un'esecuzione efficiente e una definizione concisa, consentendo al contempo un'interfaccia binaria stabile a una base di codice in evoluzione. - nota finale]
6 [Esempio:
struct trivial { trivial() = default; trivial(const trivial&) = default; trivial(trivial&&) = default; trivial& operator=(const trivial&) = default; trivial& operator=(trivial&&) = default; ~ trivial() = default; }; struct nontrivial1 { nontrivial1(); }; nontrivial1::nontrivial1() = default; // not first declaration
- fine esempio]
Quindi la domanda è ovviamente quali funzioni possono essere dichiarate implicitamente e quando ciò accade, che ho spiegato a: