[Correzione:] Non lo è. Un'eccezione nel costruttore non perderà risorse perché l'unica posizione che potrebbe verificarsi un'eccezione è all'interno dell'espressione new
e, in caso di errore di un'espressione new
, le risorse che sono state allocate da tale oggetto vengono liberate. La tua situazione è speciale perché crei una sola allocazione nel costruttore - in generale non è sicuro!
vostra frase citata si riferisce è l'operatore delete per l'oggetto-fallito il cui costruttore ha gettato:
struct T
{
T() { throw 1; }
char data[200];
};
// in your code:
T * pt = new T;
Nell'ultima riga, la memoria viene allocata prima che il costruttore viene richiamato. La memoria viene rilasciata in caso di eccezione, mediante una chiamata automatica a ::operator delete(pt)
. (In generale, l'abbinamento delete-operatore (non "espressione") che corrisponde al nuova espressione si chiama!).
Va in questo modo:
Nota che abbiamo solo abbiamo un oggetto dopo il costruttore ha completato - in modo in caso di un'eccezione nel costruttore, noi non hanno nemmeno un oggetto. Ecco perché ho detto "oggetto fallito" sopra con un trattino, perché non è affatto un oggetto (come il Douglas-fir non è affatto un abete).
Il tuo codice è potenzialmente interamente perdita non sicuro, se stai facendo più di un'assegnazione che potrebbe lanciare - cioè una perdita si verifica ogni volta che un oggetto è stato costruito con successo ma un altro, uno successivo non riesce. Si dovrebbe probabilmente solo non chiamare new
nella lista di inizializzazione e invece metterlo nel corpo:
class Danger
{
T * pt1, * pt2;
public:
Danger()
{
try { pt1 = new T; } catch(...) { throw(); }
try { pt2 = new T; } catch(...) { delete pt1; throw(); }
}
};
Oppure, dal principio della responsabilità unica, non utilizzare i puntatori prime ma contenitori che gestiscono l'utilizzo delle risorse che pulire dopo loro stessi!!
fonte
2011-08-05 00:15:06
ti fa chiedere quanto bene funzionano le implementazioni: se il costruttore di 'v_ [5]' gettato, poi sarebbe 'eliminare v _ []' solo distruggere 'v_ [0]' attraverso 'v_ [4]', e saltare quelle non costruito? –
@Mike: quelli non costruiti non devono essere distrutti (non sono mai stati creati); cosa stai dicendo che il problema è? – ildjarn
Mi chiedo se va e li distrugge comunque. (Ie vuol perdere traccia di quante si costruisce con successo?) Ora che ci penso, mi chiedo se assicura la distruzione in ordine inverso di costruzione ... –