Differenza tra syntax try-catch per la funzione

Recentemente ho trovato questa syntax per il try-catch per la funzione.

 struct A { int a; A (int i) : a(i) // normal syntax { try {} catch(...) {} } A () // something different try : a(0) {} catch(...) {} void foo () // normal function try {} catch(...) {} }; 

Entrambe le syntax sono valide . C’è qualche differenza tecnica tra queste syntax oltre allo stile di codifica? Una delle syntax è superiore ad altre da qualsiasi aspetto?

La prima syntax:
L’ambito del blocco try inizia dopo che l’elenco di inizializzazione del membro è stato completato, quindi qualsiasi eccezione generata durante l’inizializzazione del membro non verrà catturata da questo blocco try-catch.

La seconda syntax:
Assicura che se viene lanciata un’eccezione durante l’elenco di inizializzazione dei membri, è ansible rilevare l’eccezione.

La terza syntax:
Assicura che qualsiasi eccezione generata tra parentesi graffe di partenza del blocco try all’interno del corpo della funzione venga catturata in modo appropriato, significherebbe che qualsiasi eccezione causata durante il passaggio dell’argomento (se si può verificare) non verrà catturata in questo blocco try-catch.

Quindi sì, sono distintamente diversi in quale funzionalità forniscono.


MODIFICARE:
Alcune linee guida da prendere in considerazione mentre si utilizza la seconda syntax (function-try-block) in constructors & destructors:

Secondo lo standard C ++,

Se il blocco catch non gira (ripianifica l’eccezione originale o lancia qualcosa di nuovo) e il controllo raggiunge la fine del blocco catch di un costruttore o distruttore, l’eccezione originale viene automaticamente ricalcasting.

In parole semplici:
Un codice di handler del costruttore-try-block costruttore o distruttore DEVE terminare emettendo qualche eccezione.

Linea guida 1:
I gestori di funzione-try-block del costruttore hanno un solo scopo: tradurre un’eccezione. (E forse per fare il logging o qualche altro effetto collaterale.) Non sono utili per nessun altro scopo.

Lanciare un’eccezione ai distruttori è una ctriggers idea, dai un’occhiata qui per sapere perché.
Linea guida 2:
I blocchi funzione-test del distruttore non hanno alcun uso pratico. Non dovrebbe mai esserci nulla da rilevare per loro, e anche se ci fosse qualcosa da rilevare a causa del codice malvagio, il gestore non è molto utile per fare qualcosa perché non può sopprimere l’eccezione.

Linea guida 3:
Elimina sempre l’acquisizione di risorse non gestite in gestori di try-block locali all’interno del corpo del costruttore o del distruttore, mai in gestori di funzione-try-block del costruttore o del distruttore.


Per i fan Standardese:

Standard C ++, clausola 15.3, paragrafo 15:

Se un’istruzione return appare in un gestore del blocco funzione-try di un costruttore, il programma è mal formato.

Standard C ++, clausola 15.3, paragrafo 16:

L’eccezione gestita viene rimandata se il controllo raggiunge la fine di un gestore del blocco funzione-try di un costruttore o distruttore. Altrimenti, una funzione ritorna quando il controllo raggiunge la fine di un gestore per il blocco funzione-prova (6.6.3). Scorrere alla fine di una funzione-try-block equivale a un ritorno senza valore; ciò si traduce in un comportamento indefinito in una funzione di ritorno del valore (6.6.3).


Riferimenti:
Date un’occhiata a questo deve leggere la risorsa qui per maggiori dettagli e spiegazioni.

Function-try-block è utile principalmente nei costruttori, perché non c’è altro modo di catturare le eccezioni nella lista di inizializzazione. Nei distruttori bisogna fare attenzione a ritornare nel blocco catch, perché l’eccezione verrà automaticamente rilanciata. (E in buona progettazione i distruttori non devono lanciare.) Nelle funzioni normali questa funzione non è utile. Modifica: un vecchio ma ancora buono articolo: http://drdobbs.com/184401316

Potrei anche citare le specifiche … O almeno una bozza .

Sezione 15 (4):

Un blocco funzione-try associa un gestore seq con l’ inizializzatore del ctor , se presente, e l’ istruzione composta . Un’eccezione generata durante l’esecuzione dell’istruzione composta o, per costruttori e distruttori, durante l’inizializzazione o la distruzione, rispettivamente, dei sottooggetti della class, trasferisce il controllo a un gestore in un blocco funzione-try allo stesso modo di un’eccezione generata durante l’esecuzione di un try-block trasferisce il controllo ad altri handler.

(Qui il gestore-seq è la roba dopo la catch e l’ compound-statement è il corpo della funzione).

Quindi il “blocco di prova della funzione” su un costruttore o distruttore rileva le eccezioni generate dagli inizializzatori del ctor e dalla costruzione o distruzione di oggetti secondari.

Su una funzione diversa da un costruttore o un distruttore, equivale semplicemente a racchiudere il corpo della funzione. (Bene, per quanto posso discernere dalla lettura delle specifiche.)

Caratteristica interessante e nuova per me. Grazie per averlo presentato.

L’esempio “qualcosa di diverso” inserisce l’elaborazione della lista di inizializzazione nell’ambito del blocco try.