2012-07-01 8 views
30

In un paio di miei vecchi progetti di codice quando non avevo mai sentito puntatori intelligenti, ogni volta che dovevo controllare se il puntatore puntava ancora su un oggetto valido, farei sempre qualcosa di simile ...Nullptr e controlla se un puntatore punta a un oggetto valido

object * meh = new object; 
if(meh) 
    meh->member; 

O quando ho avuto bisogno di eliminare l'oggetto in modo sicuro, qualcosa di simile

if(meh) 
{ 
    delete meh; 
    meh = 0; 
} 

Bene, ora ho imparato a conoscere i problemi che possono derivare da uso di oggetti e puntatori nelle espressioni booleane sia con numeri letterali, nel modo più duro:. E ora ho anche appreso della non così nuova, ma piuttosto interessante funzionalità di C++, la parola chiave nullptr. Ma ora sono curioso.

ho già attraversato e rivisto la maggior parte del mio codice in modo che, ad esempio, quando si eliminano gli oggetti che vi scrivo

if(meh) 
{ 
    delete meh; 
    meh = nullptr; 
} 

Ora sto chiedendo circa il booleano. Quando si passa solo dire un int in un'istruzione if come questo,

int meh; 
if(meh) 

Poi controlla implicitamente per lo zero senza la necessità di scriverlo.

if(meh == 0) // does the exact same check 

Ora, il C++ farà lo stesso per i puntatori? Se passi in un char * come questo a un'istruzione if?

char * meh; 
if(meh) 

Quindi lo comparirà implicitamente con nullptr? A causa di quanto tempo ho scritto questi if in questo modo, è una seconda natura a questo punto verificare se i puntatori sono validi prima di usarli digitando if (oggetto *) e poi chiamando i suoi membri. Se questa non è la funzionalità, perché no? Troppo difficile da attuare? Risolveresti alcuni problemi rimuovendo un altro piccolo modo in cui potresti rovinare il tuo codice.

+22

È ** non ** necessario eseguire il ckeck dei puntatori prima di 'delete'ing. È completamente sicuro eliminare 'a' nullptr'. –

+1

Nel tuo ultimo esempio, intendevi 'char * meh = nullptr; if (meh) '? Il puntatore non è inizializzato. –

+3

Il risultato dell'espressione 'nuova' non sarà mai nullo, al suo posto verranno utilizzate eccezioni. Come detto, l'eliminazione di null va bene, non fa nulla. Inoltre, in genere è meglio non ripristinare il valore di un puntatore su null. L'ultima volta che viene utilizzata dovrebbe essere l'ultima volta che non è nullo, quindi l'accesso a un puntatore eliminato dovrebbe essere considerato un bug; impostandolo su null lo nasconde. – GManNickG

risposta

32

In C, tutto ciò che non è 0 è vero. Quindi, è certamente possibile utilizzare:

if (ptrToObject) 
    ptrToObject->doSomething(); 

per indicare in modo sicuro i riferimenti.

C++ 11 cambia leggermente il gioco, nullptr_t è un tipo di cui nullptr è un'istanza; la rappresentazione di nullptr_t è specifica per l'implementazione. Quindi un compilatore può definire nullptr_t come vuole. Si deve solo assicurarsi che può valere una corretta restrizione alla fusione di un nullptr_t alle diverse tipologie - di cui è consentito booleana - e assicurarsi che può distinguere tra un nullptr_t e 0.

Quindi nullptr sarà cast correttamente e implicitamente allo booleanofalse a condizione che il compilatore segua le specifiche del linguaggio C++ 11. E il frammento di sopra funziona ancora.

Se si elimina un oggetto di riferimento, non viene modificato nulla.

delete ptrToObject; 
assert(ptrToObject); 
ptrToObject = nullptr; 
assert(!ptrToObject); 

A causa di quanto tempo ho scritto queste IFS come questo, è una seconda natura, a questo punto per verificare se i puntatori validi prima di usare digitando se (oggetto *) e quindi chiamando sono membri.

No. favore mantenere un corretto grafico di oggetti (preferibilmente utilizzando puntatori univoci/intelligenti). Come sottolineato, non c'è modo di determinare se un puntatore che non è nullptr punta a un oggetto valido o meno. L'onere è su di te per mantenere comunque il ciclo di vita .. questo è il motivo per cui i wrapper puntatori esistono in primo luogo.

+0

beh, lo sapevo. se lasciato senza confronto, se le istruzioni controllano se qualunque cosa viene passata risolve in letterale qualsiasi cosa tranne 0. se int meh = 0 allora si risolve falso. tuttavia se l'indirizzo di dire un int * è 0x000 ecc, significa che non punta a nulla e il bool si risolverà falso. se punta a qualche parte, allora non è zero e poi si risolve in modo vero. ma cosa succede se si elimina l'oggetto sul puntatore? il ptr stil contiene l'indirizzo 0x81A3 o qualcosa del genere, ma l'oggetto è sparito. tu chiami il se, e si risolve vero, anche se non c'è un oggetto lì. – FatalCatharsis

+1

che causerebbe un errore di runtime, se si è dimenticato di azzerare il puntatore. ma se il puntatore è stato confrontato implicitamente con nullptr, quindi se il puntatore era 0 o indirizzato a qualcosa, sarebbe stato risolto false quando l'oggetto non era presente. – FatalCatharsis

+2

Sì. Allora, qual è la tua domanda? – dcow

6

Non è possibile verificare se un puntatore punta o meno su un oggetto valido. Se il puntatore non è nullo ma non punta a un oggetto valido, l'uso del puntatore causa un comportamento non definito. Per evitare questo tipo di errore, è necessario che tu faccia attenzione alla durata degli oggetti puntati; e le classi di puntatori intelligenti aiutano con questo compito.

Se meh è un puntatore grezzo poi c'è alcuna differenza tra if (meh) e if (meh != 0) e if (meh != nullptr). Tutti procedono se il puntatore non è nullo.

Esiste una conversione implicita dal valore letterale 0 a nullptr.

Problemi correlati