Perché non cancella il puntatore su NULL?

Mi sono sempre chiesto perché l’impostazione automatica del puntatore su NULL dopo l’ eliminazione non è parte dello standard. Se ciò viene risolto, molti degli arresti dovuti a un puntatore non valido non si verificano. Ma avendo detto che posso pensare a un paio di motivi per cui lo standard avrebbe limitato questo:

  1. Prestazione:

    Un’istruzione aggiuntiva potrebbe rallentare le prestazioni di delete .

  2. Potrebbe essere a causa di puntatori const .

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

Qualcuno sa esattamente le ragioni per non permettere questo?

Lo stesso Stroustrup risponde. Un estratto:

C ++ consente esplicitamente un’implementazione di delete per azzerare un operando lvalue, e speravo che le implementazioni lo avrebbero fatto, ma quell’idea non sembra essere diventata popolare con gli implementatori.

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

Innanzitutto, l’impostazione su null richiederebbe una variabile memorizzata nella memoria. È vero che di solito hai un puntatore in una variabile, ma a volte potresti voler eliminare un object in un indirizzo appena calcolato. Sarebbe imansible cancellare “annullando”.

Poi arriva la prestazione. È ansible che il codice sia stato scritto in modo che il puntatore esca dall’ambito immediatamente dopo l’ eliminazione . 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.

È ansible 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 objective simile in un modo diverso).

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.

Inoltre, puoi creare la tua funzione che fa ciò che vuoi:

 template void deleten(T *&ptr) { delete ptr; ptr = NULL; } 

Perché non ce n’è davvero bisogno e perché richiederebbe l’eliminazione di un puntatore a puntatore anziché un puntatore.

delete è usato principalmente nei distruttori, nel qual caso l’impostazione di un membro su NULL è inutile. Alcune righe dopo, alla chiusura } , 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; 

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 🙂

C ++ consente di definire il proprio operatore nuovo ed eliminare in modo che, ad esempio, utilizzino il proprio pool di allocatori. Se si esegue questa operazione, è ansible 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).
Pertanto, l’eliminazione automatica di NULL nel suo argomento non ha sempre il significato di: impostare il valore su un valore non valido. Il valore non valido potrebbe non essere sempre NULL.

Ecco un’altra ragione; supponiamo che delete imposti il ​​suo argomento su NULL:

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

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

La filosofia del C ++ è “paghi solo se la usi”. Penso che possa rispondere alla tua domanda.

Inoltre a volte potresti avere il tuo heap che recupererà la memoria cancellata … o qualche volta il puntatore non è di proprietà di alcuna variabile. O puntatore memorizzato in poche variabili: è ansible azzerarne solo uno.
Come puoi vedere ha molti problemi e possibili problemi.

L’impostazione automatica del puntatore su NULL non risolve la maggior parte dei problemi con l’utilizzo di puntatori non valido. 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.

Vedo persone che danno risposte strane a questa domanda.

ptr = NULL; In che modo una semplice affermazione 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 delete per funzionare in questo modo. Pensava che i programmatori si sarebbero presi cura di questo. Quindi ha ignorato.