2013-08-05 16 views
14

Secondo C++ reference, Potete nuovo un oggetto da:Perchè nuova versione std :: nothrow non viene ampiamente utilizzato

MyClass * p1 = new MyClass; 

o

MyClass * p2 = new (std::nothrow) MyClass; 

Il secondo restituisce un puntatore nullo, invece di lanciare un'eccezione

Tuttavia, difficilmente vedo questa versione nella mia esperienza.

Ad esempio, Google sconsiglia di utilizzare l'eccezione nel codice, ma non utilizzano la versione nothrow in Chromium, come posso vedere.

C'è qualche motivo per cui preferiamo quello predefinito rispetto a quello nothrow? Anche in un progetto che non utilizza l'eccezione?

- EDIT -

Follow up domanda: dovrei controllare il valore di ritorno di malloc()?

Sembra, al contrario, molte persone consiglio per controllare il valore di ritorno di malloc, alcuni hanno detto, perché:

molti errori di allocazione non hanno nulla a che fare con l'essere esaurito la memoria. La frammentazione può causare il fallimento di un'assegnazione perché non è disponibile spazio contiguo sufficiente anche se la memoria è piena.

È vero? Perché trattiamo in questo caso malloc() e new() in questo caso?

+0

Se il nuovo tentativo fallisce, è molto probabile che si esaurisca la memoria e sia necessario uscire comunque ... – Kelm

+1

Nota che in altre lingue, come java, distinguiamo tra * un'eccezione * e un * errore * (che è * di solito * fatale). In java, la memoria insufficiente è un * errore * e NON un * eccezione *. – amit

+1

Oltre a chiedere un'opinione, la tua domanda di chiusura sembra contraddittoria. Per definizione, se si utilizza la versione di lancio delle eccezioni, si utilizzano eccezioni, rendendo in tal modo discutibile il punto "Anche in un progetto che non utilizza eccezioni". Se con "non si usano eccezioni" si intende che non si hanno blocchi try-catch e quindi il runtime catturerà l'eccezione e terminerà il programma (di solito) si * lo * si usa usando le eccezioni; non stai semplicemente * gestendoli * nel tuo codice scritto. – WhozCraig

risposta

23

Tuttavia, difficilmente vedo questa versione nella mia esperienza.

Si utilizzerà (o, equivalentemente, si cattura l'eccezione dalla versione predefinita) se è possibile gestire l'errore localmente; forse richiedendo di liberare qualche altra memoria e poi riprovando, o tentando di allocare qualcosa di più piccolo, o usando un algoritmo alternativo che non ha bisogno di memoria extra.

C'è qualche motivo per cui preferiamo quello predefinito rispetto a quello nothrow?

Il principio generale di eccezioni: se non è possibile gestirlo localmente, non è necessario controllare localmente. A differenza dei valori di ritorno, le eccezioni non possono essere ignorate, quindi non c'è possibilità di arare su indipendentemente e usando un puntatore nullo.

Anche in un progetto che non utilizza l'eccezione?

Spesso, una condizione di esaurimento della memoria non può essere gestita affatto. In tal caso, terminare il programma è probabilmente la migliore risposta; e questa è la risposta predefinita a un'eccezione non gestita. Quindi, anche se non stai usando le eccezioni, l'impostazione predefinita è new probabilmente nella maggior parte delle situazioni.

devo controllare il valore di ritorno di malloc()?

Sì: questo è l'unico modo per verificare se è riuscito. Se non lo fai, potresti finire usando un puntatore nullo, dando un comportamento indefinito: spesso un crash, ma forse corruzione dei dati o altro comportamento bizzarro e lunghe sessioni di debug per (si spera) capire cosa è andato storto.

Perché trattiamo in questo caso malloc() e new in questo caso?

perché malloc forze noi per controllare il valore di ritorno, mentre new ci dà la possibilità di gestione degli errori meno invadente.

4

Se si utilizza la versione di lancio, non è necessario verificare il risultato di ogni chiamata new per verificare se è riuscita o meno. Tipicamente parlando in molte/più applicazioni se la tua allocazione fallisce non puoi fare molto e solo uscire/uscire, che l'eccezione fa automaticamente per te se non provi/prendi esplicitamente.

Se si utilizza la versione nothrow, è possibile che si verifichi la propagazione di un puntatore nullo tramite l'applicazione e si verifichi un arresto anomalo/successivo di MUCH in un punto apparentemente totalmente estraneo all'allocazione di memoria, rendendo molto più difficile il debug.

Problemi correlati