2009-04-01 14 views
108

Mi sono sempre chiesto perché l'impostazione automatica del puntatore su NULL dopo elimina non fa parte dello standard. Se ciò viene risolto, molti degli arresti dovuti a un puntatore non valido non si verificano. Ma detto questo mi viene in mente paio di motivi per cui lo standard si sarebbe limitato a questo:Perché non cancella il puntatore su NULL?

  1. Performance:

    Un'istruzione supplementare potrebbe rallentare le prestazioni delete.

  2. Potrebbe essere a causa di const puntatori.

    Quindi di nuovo lo standard avrebbe potuto fare qualcosa per questo caso speciale, immagino.

Qualcuno sa motivi esatti di non permettere questo?

risposta

138

Stroustrup himself risposte. Un estratto:

C++ permette esplicitamente un implementazione di cancellazione per azzerare un operando lvalue, e avevo sperato che le implementazioni lo farebbero, ma l'idea non sembra avere diventato popolare con esecutori.

Ma il problema principale che solleva è che l'argomento di cancellazione non deve essere un valore.

12

Perché non ce n'è davvero bisogno e perché richiederebbe il rilevamento da puntatore a puntatore anziché puntatore.

+1

Oppure riferimento al puntatore. –

+0

true, ma ciò comporterebbe lo stesso overhead – snemarch

5

Se si dispone di un array di puntatori e la seconda azione consiste nell'eliminare l'array vuoto, non è necessario impostare ogni valore su null quando la memoria sta per essere liberata. Se vuoi che sia nullo .. scrivi null ad esso :)

54

Per prima cosa, l'impostazione su null richiederebbe una variabile di memoria memorizzata. È vero, di solito hai un puntatore in una variabile ma a volte potresti voler eliminare un oggetto con un indirizzo appena calcolato. Sarebbe impossibile cancellare "annullando".

Poi arriva la prestazione. È possibile che il codice sia stato scritto in modo che il puntatore esca immediatamente dopo che elimina. Riempirlo con null è solo una perdita di tempo. E il C++ è una lingua con l'ideologia "non ne ha bisogno? Quindi non devi pagare per questo".

Se hai bisogno di sicurezza c'è una vasta gamma di puntatori intelligenti al tuo servizio o puoi scrivere la tua - migliore e più intelligente.

+4

L'indirizzo calcolato di Good Point Wrt, anche se è qualcosa che non si vede spesso – snemarch

+0

stai parlando di posizionamento nuovo quando dici che a volte potresti voler eliminare un oggetto in un solo indirizzo calcolato ??? – Destructor

+0

@PravasiMeet No, intendo qualcosa come 'delete (ptr + i)' – sharptooth

35

È possibile avere più puntatori che puntano a quella memoria. Creerebbe un falso senso di sicurezza se il puntatore specificato per l'eliminazione fosse impostato su null, ma tutti gli altri puntatori no. Un puntatore non è altro che un indirizzo, un numero. Potrebbe anche essere un int con un'operazione di dereferenziazione. Il mio punto è che dovresti scansionare anche ogni singolo puntatore per trovare quelli che fanno riferimento alla stessa memoria che hai appena cancellato e annullarli. Sarebbe computazionalmente intenso scansionare tutti i puntatori per quell'indirizzo e annullarli, perché la lingua non è progettata per questo. (Sebbene alcuni altri linguaggi strutturino i loro riferimenti per raggiungere un obiettivo simile in un modo diverso.)

17

Un puntatore può essere salvato in più di una variabile, impostando uno di questi su NULL lascerebbe comunque i puntatori non validi nelle altre variabili. Quindi in realtà non guadagni molto, è più probabile che crei un falso senso di sicurezza.

Oltre a questo, è possibile creare la propria funzione che fa quello che si vuole:

template<typename T> 
void deleten(T *&ptr) { 
    delete ptr; 
    ptr = NULL; 
} 
4

C++ consente di definire il proprio operatore new e delete in modo che, per esempio avrebbero usato la propria piscina allocatore. Se si esegue questa operazione, è possibile utilizzare nuovi ed eliminare con elementi che non sono indirizzi rigorosi, ma indicare indici nel pool pool. In questo contesto, il valore di NULL (0) potrebbe avere un significato legale (facendo riferimento al primo elemento nel pool).
Quindi avere automaticamente impostato NULL sul suo argomento non ha sempre il significato di - imposta il valore su un valore non valido. Il valore non valido potrebbe non essere sempre NULL.

3

L'impostazione del puntatore su NULL non risolve automaticamente la maggior parte dei problemi relativi all'utilizzo errato del puntatore. L'unico incidente che eviterebbe è se si tenta di eliminarlo due volte. Cosa succede se si chiama una funzione membro su un puntatore del genere? Crollerebbe ancora (supponendo che acceda alle variabili membro). C++ non ti limita a chiamare alcuna funzione sui puntatori NULL, né dovrebbe farlo dal punto di vista delle prestazioni.

4

La filosofia del C++ è "paga solo se la usi". Penso che possa rispondere alla tua domanda.

Anche a volte è possibile avere il proprio heap che recupera la memoria cancellata .. o talvolta il puntatore non è di proprietà di alcuna variabile. O puntatore memorizzato in poche variabili: è possibile azzerarne solo uno.
Come potete vedere ha molti problemi e possibili problemi.

7

delete viene utilizzato principalmente nei distruttori, nel qual caso l'impostazione di un membro su NULL è inutile. Alcune righe dopo, al momento della chiusura dello }, il membro non esiste più. Negli operatori di assegnazione, un'eliminazione è in genere seguita da un'assegnazione comunque.

Inoltre, renderebbe il seguente codice illegale:

T* const foo = new T; 
delete foo; 
4

Ecco un altro motivo; supponiamo che delete faccia impostare il suo argomento a NULL:

int *foo = new int; 
int *bar = foo; 
delete foo; 

La barra dovrebbe essere impostata su NULL? Puoi generalizzare questo?

-2

Vedo persone che danno risposte strane a questa domanda.

ptr = NULL; In che modo una semplice istruzione può causare ritardi nelle prestazioni?

Un'altra risposta sta dicendo che possiamo avere più puntatori che puntano alla stessa posizione di memoria . Sicuramente possiamo.In questo caso, l'operazione di cancellazione su un puntatore renderebbe NULL solo quel puntatore (se delete stava rendendo il puntatore NULL) e l'altro puntatore non sarebbe NULL e punterebbe alla posizione di memoria che è libera.

La soluzione per questo dovrebbe essere che l'utente dovrebbe eliminare tutti i puntatori che puntano alla stessa posizione. Internamente dovrebbe controllare se la memoria è già liberata di quanto non sia gratuita. Crea solo il puntatore NULL.

Stroustrup potrebbe aver progettato di eliminare per funzionare in questo modo. Pensava che i programmatori si sarebbero presi cura di questo. Quindi ha ignorato.

Problemi correlati