Perché non elimina impostare il puntatore su NULL?


127

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

  1. Prestazione:

    Un'istruzione aggiuntiva potrebbe rallentare le deleteprestazioni.

  2. Potrebbe essere a causa di constpuntatori.

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

Qualcuno conosce i motivi esatti per non consentire questo?

Risposte:


150

Lo stesso Stroustrup risponde. Un estratto:

Il C ++ consente esplicitamente un'implementazione di delete per azzerare un operando lvalue e avevo sperato 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 delete non deve necessariamente essere un valore.


Penso che questo potrebbe usare qualche spiegazione in più. Non sono nemmeno sicuro di quello che sta dicendo ... Suppongo che dovrò tornare più tardi, quando potrò dedicare un paio d'ore alla ricerca di questo fino a quando non lo avrò. Oppure, potresti spiegare la risposta per aiutarci a capire più rapidamente.
Gabriel Staples,

63

Innanzitutto, l'impostazione su null richiederebbe una variabile memorizzata in memoria. È vero, di solito hai un puntatore in una variabile ma a volte potresti voler eliminare un oggetto a un indirizzo appena calcolato. Ciò sarebbe impossibile con l'eliminazione "annullamento".

Poi arriva la performance. È possibile che il codice sia stato scritto in modo tale che il puntatore esca dall'ambito immediatamente dopo l' eliminazione . Riempirlo con null è solo una perdita di tempo. E C ++ è un linguaggio con l'ideologia "non ne hai bisogno? Quindi non devi pagarlo".

Se hai bisogno di sicurezza c'è una vasta gamma di puntatori intelligenti al tuo servizio o puoi scrivere i tuoi - meglio e più intelligenti.


4
Un buon punto per l'indirizzo calcolato, anche se è qualcosa che non vedi spesso
snemarch

stai parlando di un posizionamento nuovo quando dici che a volte potresti voler eliminare un oggetto a un indirizzo appena calcolato. ???
Distruttore,

@PravasiMeet No, intendo qualcosa del generedelete (ptr + i)
sharptooth,

39

Puoi 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 non tutti gli altri puntatori. Un puntatore non è altro che un indirizzo, un numero. Potrebbe anche essere un int con un'operazione di dereference. Il punto è che dovresti anche scansionare ogni singolo puntatore per trovare quelli che fanno riferimento alla stessa memoria che hai appena eliminato e annullarli. Sarebbe intenso dal punto di vista computazionale scansionare tutti i puntatori per quell'indirizzo e annullarli, perché il linguaggio non è progettato per quello. (Anche se alcune altre lingue strutturano i loro riferimenti per raggiungere un obiettivo simile in modo diverso.)


19

Un puntatore può essere salvato in più di una variabile, impostando uno di questi su NULL rimarrebbero comunque puntatori non validi nelle altre variabili. Quindi non guadagni molto, stai probabilmente creando un falso senso di sicurezza.

Oltre a ciò, puoi creare la tua funzione che fa quello che vuoi:

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

12

Perché non ce n'è davvero bisogno e perché richiederebbe l'eliminazione prendendo il puntatore al puntatore anziché solo il puntatore.


vero, ma ciò comporterebbe lo stesso sovraccarico
snemarch

7

deleteviene utilizzato 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, in genere un'eliminazione è seguita da un'assegnazione.

Inoltre, renderebbe illegale il seguente codice:

T* const foo = new T;
delete foo;

6

Ecco un altro motivo; 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?


5

Se si dispone di una matrice di puntatori e la seconda azione consiste nell'eliminare la matrice vuota, non vi è alcun punto che imposta ogni valore su null quando la memoria sta per essere liberata. Se vuoi che sia nullo .. scrivici null :)


4

C ++ consente di definire il proprio operatore nuovo ed eliminarlo in modo tale che, ad esempio, utilizzino il proprio allocatore di pool. Se lo fai, allora è possibile usare new ed eliminare con cose che non sono strettamente indirizzi ma che dicono indici nella matrice del pool. In questo contesto, il valore di NULL (0) potrebbe avere un significato legale (facendo riferimento al primo elemento nel pool).
Pertanto, l'eliminazione impostata su NULL automaticamente sul 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.


4

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

Inoltre a volte potresti avere il tuo heap che ripristinerà la memoria eliminata .. o a volte puntatore non di proprietà di nessuna variabile. O puntatore memorizzato in poche variabili: è possibile zero solo una di esse.
Come puoi vedere ha molti problemi e possibili problemi.


3

L'impostazione automatica del puntatore su NULL non risolverà la maggior parte dei problemi con un utilizzo errato del puntatore. L'unico crash che eviterebbe è se si tenta di eliminarlo due volte. Cosa succede se si chiama una funzione membro su tale puntatore? Si bloccherebbe comunque (supponendo che acceda alle variabili membro). C ++ non ti impedisce di chiamare alcuna funzione sui puntatori NULL, né dovrebbe farlo dal punto di vista delle prestazioni.


-1

Vedo persone che danno risposte strane a questa domanda.

ptr = NULL; In che modo un'istruzione così semplice può causare un ritardo 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 eliminazione su un puntatore renderebbe solo quel puntatore NULL (se delete stava rendendo il puntatore NULL) e l'altro puntatore sarebbe non-NULL e punta alla posizione della memoria che è libera.

La soluzione per questo dovrebbe essere che l'utente dovrebbe eliminare tutti i puntatori che puntano alla stessa posizione. Internamente dovrebbe verificare se la memoria è già libera di non liberare. Rendi solo il puntatore NULL.

Stroustrup potrebbe aver progettato l'eliminazione per funzionare in questo modo. Pensava che i programmatori se ne sarebbero occupati. Quindi ha ignorato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.