2012-05-25 12 views
6

Come si vede attraverso il commento, il distruttore della classe Error fornisce esplicitamente un'implementazione vuota con identificatore di non lancio.Dovremmo fornire un distruttore con identificatore di non lancio?

Domanda: È necessario? O è una buona pratica comparativa per consentire al compilatore di generare un distruttore implicito?

+0

Ho dovuto aggiungere un distruttore no-throw alla mia classe di eccezione derivata da std :: exception per eliminare un avviso o un errore che gcc emetteva quando non ne avevo fornito uno. Non mi piaceva che la classe derivata non avesse la stessa specifica di non lancio della classe base. –

+1

* Se * decidi di farlo, userei 'noexcept' invece di' throw() ', se possibile. Le specifiche delle eccezioni dinamiche (incluso 'throw()', almeno così come l'ho letta) sono deprecate (anche se il tuo compilatore non è all'altezza, potresti non essere in grado di farlo). –

risposta

8

In C++ 11, i distruttori sono implicitamente throw() (a meno che qualsiasi membro o base del tipo abbia un distruttore con una specifica di eccezione diversa) quindi se si sta compilando in modalità C++ 11 non è necessario.

Se si è in C++ 03, è possibile aggiungerlo, ma se avrà un effetto o meno è definito molto all'implementazione ... Ora, per scopi di documentazione, si potrebbe desiderare di aggiungerlo, ma di nuovo , si presume comunemente che i distruttori non lanciano.

+0

Credo che non sia accurato su C++ 11. – bames53

+0

In C++ 11, un agente ha implicitamente una specifica di eccezione che è fondamentalmente l'unione di qualsiasi cosa generata da qualcosa che chiama direttamente. È solo se non chiama nulla che getta. [Almeno credo che sia l'intento - la formulazione è un po 'confusa, quindi è almeno discutibilmente auto-contraddittorio in questo momento]. –

+3

Ho passato questa parte dello standard con un collega alcune settimane fa, e il problema è che la specifica dell'eccezione (se non è stata data per il distruttore) sarebbe quella di un distruttore implicitamente dichiarato, che a sua volta è l'unione delle specifiche di eccezione di tutte le funzioni che la * definizione implicita * di quel distruttore chiamerebbe, che sono i distruttori di tutti i membri e le basi. La nostra comprensione al momento è che '~ Error() {throw 1; f(); } 'avrebbe una specifica di eccezione' noexcept (true) 'anche se' f' getta ... –

4

Dipende da cosa si pensa throw() significa.

Ciò che in realtà significa in base allo standard è "inserire codice aggiuntivo per ogni chiamata a questa funzione, se necessario, o nella funzione stessa, per garantire che se questa funzione viene lanciata, viene rilevata l'eccezione e viene chiamato std::unexpected" .

Alcuni compilatori lo hanno implementato per significare "ottimizzare le chiamate a questa funzione supponendo che non generino", ma (in violazione dello standard) non ha implementato il controllo di runtime.

Quindi, aggiungendolo a un distruttore (che di certo non dovrebbe lanciare) (ma in pratica potrebbe non esserlo) aggiungere un controllo di runtime che non dovrebbe mai essere attivato e quindi potrebbe aiutare a eseguire il debug del codice. Può o non può consentire un'ottimizzazione.

3

distruttori sempre implicitamente hanno specifiche eccezioni:

[class.dtor] 12.4 p3

Una dichiarazione di un distruttore che non ha una specifica delle eccezioni è implicitamente considerato di avere la stessa eccezione- specifica come dichiarazione implicita (15.4).

[except.spec] 15,4 p14

Un implicitamente dichiarata funzione di membro speciale (clausola 12) deve avere una specifica delle eccezioni. Se f è un costruttore predefinito implicitamente dichiarato, un costruttore di copia, un costruttore di movimento, un distruttore, un operatore di assegnazione di copia o un operatore di spostamento, la sua specifica di eccezione implicita specifica l'id di tipo T se e solo se T è consentito dalla specifica di eccezione di una funzione invocata direttamente dalla definizione implicita di f; f deve consentire tutte le eccezioni se qualsiasi funzione invocata direttamente consente tutte le eccezioni, e f non deve consentire eccezioni se ogni funzione invocata direttamente non consente eccezioni.

Quindi, no, non è necessario per l'utente utilizzare una specifica di eccezione.


in C++ 03 utenti distruttori definiti non hanno una specifica eccezione implicita, quindi se si fa definire il proprio distruttore non si può fare affidamento sul compilatore per aggiungere automaticamente la specifica eccezione appropriata. Ma i distruttori dichiarati implicitamente hanno la stessa specifica di eccezione implicita di C++ 11.

+0

@SteveJessop: la prima citazione (§12.4/3) è nuova in C++ 11. In C++ 03, la seconda citazione è numerata §15.4/13, ma (credo) ha la stessa formulazione. –

Problemi correlati