[C++] Chiarimento sull'operatore delete
Da quel che ho capito, delete dichiara libera la zona di memoria puntata da un puntatore, ma non cancella il contenuto delle locazioni di memoria puntate né tocca l'indirizzo a cui punta il puntatore.
Però se scrivo questo codice:
...la zona di memoria puntata da p_float è la stessa, ma ottengo due risultati diversi quando dereferenzio. Perché? Pensavo che delete non toccasse il contenuto di quella zona di memoria.
Però se scrivo questo codice:
float *p_float = new float; *p_float=5.456e-4; cout << p_float << " " << *p_float << endl; delete p_float; cout << p_float << " " << *p_float << endl;
...la zona di memoria puntata da p_float è la stessa, ma ottengo due risultati diversi quando dereferenzio. Perché? Pensavo che delete non toccasse il contenuto di quella zona di memoria.
Risposte
Dereferenziare un puntatore dopo aver usato delete su di esso è un undefined behaviour, quindi in linea di principio il compilatore può generare codice qualsiasi (e quindi è sempre un errore). In realtà, però, la maggior parte dei compilatori hanno un comportamento relativamente deterministico, anche in questi casi.
Una possibilità è che l'implementazione di "cout << qualcosa" usi allocazione dinamica della memoria, e, dato che l'area di memoria puntata da p_float è libera, potrebbe sovrascriverla prima di leggerla per stampare l'output. Per verificare, potresti prima copiare il contenuto di *p_float in un'altra variabile, e stampare quella.
Inoltre, per tipi complessi (classi), delete chiama anche il relativo distruttore, che potrebbe sovrascrivere la memoria puntata.
Una possibilità è che l'implementazione di "cout << qualcosa" usi allocazione dinamica della memoria, e, dato che l'area di memoria puntata da p_float è libera, potrebbe sovrascriverla prima di leggerla per stampare l'output. Per verificare, potresti prima copiare il contenuto di *p_float in un'altra variabile, e stampare quella.
Inoltre, per tipi complessi (classi), delete chiama anche il relativo distruttore, che potrebbe sovrascrivere la memoria puntata.
Dichiarare della memoria libera può anche significare modificare la memoria. Per esempio memorizzando nel blocco di memoria informazioni su dove trovare il prossimo blocco di memoria libero o la dimensione del blocco corrente o altro. Il comportamento può inoltre cambiare in base a tantissime variabili come la dimensione del blocco allocato/deallocato o lo stato del sistema in quel momento. Una importante regola del C/C++ è di non deferenziare un puntatore a memoria già deallocata.
Chiarissimo, grazie a entrambi!
