2010-10-23 12 views
11

ho il codice seguente, che non può essere compilato:Come posso richiamare la versione nothrow di delete?

int *p = new(nothrow) int; 
delete (nothrow) p; //Error 

L'errore che ottengo è:

errore C2440: 'delete': impossibile convertire da 'std :: const nothrow_t' a 'void *'

Fa una versione nothrow di delete esiste? In tal caso, come posso invocarlo?


In C++: il riferimento completo, è dato che esiste ma ho visto diverse opinioni online, quindi la confusione.

MSDN parla anche della sua esistenza, ma non ho trovato il modo in cui può essere utilizzato nel codice.

Here, alcune persone dicono che non esiste una cosa del genere.

+0

Il tuo link MSDN parla dell'esistenza di 'nothrow', ma * che * non ha mai avuto alcun dubbio. È * 'delete' * che tutti ti dicono che non ha la versione' nothrow', e hanno ragione. –

+3

Se quel libro è quello di Schildt, dovresti (sfortunatamente) buttarlo via. Quel ragazzo è terribile e non ha idea di cosa stia parlando quando parla della lingua. – GManNickG

risposta

15

A esiste una funzione di deallocazione std::nothrow_t, ma non è possibile chiamarla con un'espressione delete.

La funzione di deallocazione è lì per completezza. Se un'espressione new non riesce a causa di un'eccezione, il compilatore deve liberare la memoria allocata tramite operator new con una chiamata allo operator delete. Quindi deve esserci un operator delete che accetta uno std::nothrow_t, per consentire questo.

(Cioè, in generale, un new espressione con la forma new (args...) T allocherà memoria con una chiamata a operator new(sizeof(T), args...). Per "match" significa chiamare operator delete gli stessi argomenti, tranne la prima.)

Note puoi chiamare direttamente l'operatore: operator delete(memory, std::nothrow);. Tuttavia, un'espressione delete non chiama mai una funzione di deallocazione globale con parametri aggiuntivi.


Così si può "call" con:

struct always_throw 
{ 
    always_throw() { throw std::exception(); } 
}; 

new (std::nothrow) always_throw; 

Ad un certo punto, questo sarà allocare la memoria con una chiamata a:

void* __memory = operator new(sizeof(always_throw), std::nothrow); 

Dal momento che l'inizializzazione dell'oggetto getta , il compilatore deve liberare la memoria allocata con una funzione di deallocazione corrispondente, così fa:

operator delete(__memory, std::nothrow); 

Chiamare la versione std::nothrow_t.

5

Non esiste una forma di delete, perché delete non buttare, in quanto:

  1. non esegue alcuna allocazioni.
  2. È spesso utilizzato in distruttori che non dovrebbero lanciare!

I prodotti creati con la versione nothrow di nuovo, tornerà NULL invece di lanciare un'eccezione bad_alloc. L'utilizzo di delete su NULL è perfettamente valido, quindi non c'è nessuna situazione dove dovrebbe essere lanciato.

+0

Oh. Ma in riferimento completo C++ book, è dato che esiste e ho visto diverse opinioni diverse in internet, quindi la confusione. – bjskishore123

+1

Cosa intendi per "non sono stati allocati dall'heap"? Assegna ancora memoria, semplicemente non getterà se non può. – GManNickG

+0

Mi spiace, aggiornato per essere meno confuso e non confondere con il nuovo posto ... –

2

Per scopi pratici, c'è solo una versione di eliminazione. Lo new(nothrow) viene scritto come nuovo operatore di posizionamento, ma per la maggior parte non esiste una versione corrispondente per l'eliminazione. L'unica eccezione a questa è una versione di eliminazione che viene richiamata quando un nuovo posizionamento getta - ma poiché (in questo caso) hai assicurato che il new non può essere lanciato, quella versione di eliminazione non è di reale utilità/aiuto Qui.

Problemi correlati