Eliminazione di un puntatore a const (T const *)


89

Ho una domanda di base sui puntatori const. Non sono autorizzato a chiamare alcuna funzione membro non const utilizzando un puntatore const. Tuttavia, sono autorizzato a farlo su un puntatore const:

delete p;

Questo chiamerà il distruttore della classe che in sostanza è un "metodo" non const. Perché è permesso? È solo per supportare questo:

delete this;

O c'è qualche altra ragione?

Risposte:


112

È per supportare:

// dynamically create object that cannot be changed
const Foo * f = new Foo;

// use const member functions here

// delete it
delete f;

Ma nota che il problema non è limitato agli oggetti creati dinamicamente:

{
 const Foo f;
 // use it
} // destructor called here

Se i distruttori non possono essere chiamati su oggetti const, non potremmo usare affatto oggetti const.


21
+1 per l'ultima tua modifica. Penso che questa sia la vera ragione. Chiamata automatica del distruttore per l'oggetto const - quasi uguale a delete f; dove f - puntatore su const.
bayda

const Foo * fo Foo const * fnon è un puntatore const a Foo. È bello constare Foo. Foo * const f è un puntatore const a Foo.
user11373693

48

Mettiamola in questo modo: se non fosse consentito non ci sarebbe modo di eliminare oggetti const senza usare const_cast.

Semanticamente, const è un'indicazione che un oggetto dovrebbe essere immutabile. Ciò non implica, tuttavia, che l'oggetto non debba essere eliminato.


3
I distruttori possono mutare oggetti in modi piuttosto violenti, quindi questo deve essere uno strano uso della parola "immutabile" di cui non ero a conoscenza ...
DarthGizka

1
@DarthGizka no, i distruttori ti portano da uno stato in cui c'è un oggetto a uno in cui non c'è. Il C ++ non definisce alcun metodo per osservare una "mutazione" dopo la distruzione
Caleth

@ Caleth: lo standard potrebbe non permetterti di guardare l'oggetto dopo che il suo distruttore è stato completato, ma ti è certamente permesso di guardare gli effetti collaterali causati dalla distruzione. Quindi le circostanze possono essere facilmente organizzate per rendere osservabile la mutazione dell'oggetto "immutabile". Negli Stati Uniti, l'omicidio è difficile da perseguire quando non c'è un corpo, ma è ancora un omicidio (e potrebbero esserci altre prove sufficienti per una condanna). Stessa differenza.
DarthGizka,

6

Non sono autorizzato a chiamare alcuna funzione membro non const utilizzando un puntatore const.

Sì, sei tu.

class Foo
{
public:
  void aNonConstMemberFunction();
};

Foo* const aConstPointer = new Foo;
aConstPointer->aNonConstMemberFunction(); // legal

const Foo* aPointerToConst = new Foo;
aPointerToConst->aNonConstMemberFunction(); // illegal

Hai confuso un puntatore const a un oggetto non const, con un puntatore non const a un oggetto const.

Avendolo detto,

delete aConstPointer; // legal
delete aPointerToConst; // legal

è legale eliminarli entrambi, per i motivi già indicati dalle altre risposte qui.


5

I costruttori e i distruttori non dovrebbero essere visti come "metodi". Sono costrutti speciali per inizializzare e abbattere un oggetto di una classe.

'const pointer' indica che lo stato dell'oggetto non verrebbe modificato quando vengono eseguite operazioni su di esso mentre è attivo.


5

Un altro modo di vederlo: il significato preciso di un puntatore const è che non sarai in grado di apportare modifiche all'oggetto puntato che sarebbe visibile tramite quello o qualsiasi altro puntatore o riferimento allo stesso oggetto. Ma quando un oggetto si distrugge, tutti gli altri puntatori all'indirizzo precedentemente occupato dall'oggetto ora eliminato non sono più puntatori a quell'oggetto . Memorizzano lo stesso indirizzo, ma quell'indirizzo non è più l'indirizzo di alcun oggetto (infatti potrebbe presto essere riutilizzato come indirizzo di un oggetto diverso).

Questa distinzione sarebbe più ovvia se i puntatori in C ++ si comportassero come riferimenti deboli, cioè non appena l'oggetto viene distrutto, tutti i puntatori esistenti ad esso verrebbero immediatamente impostati su 0. (Questo è il genere di cose considerate troppo costose in fase di esecuzione da imporre a tutti i programmi C ++, e in effetti è impossibile renderle completamente affidabili.)

AGGIORNAMENTO : Rileggendolo nove anni dopo, è un avvocato. Ora trovo comprensibile la tua reazione originale. Non consentire la mutazione ma consentire la distruzione è chiaramente problematico. Il contratto implicito dei puntatori / riferimenti const è che la loro esistenza agirà come un blocco sulla distruzione dell'oggetto di destinazione, alias garbage collection automatica.

La solita soluzione a questo è usare quasi qualsiasi altra lingua invece.


Se non puoi distruggere le cose indicate dai puntatori a const, come gestisci una std::unique_ptr<const T>fine della sua vita?
Caleth

@Caleth quindi non ci sarebbe alcuna soluzione a questo in C ++. Questo è solo un esempio del problema generale: in C ++ il modificatore const significa "Non puoi mutare il target, tranne in un senso in cui puoi distruggerlo completamente e rendere tutti gli altri riferimenti ad esso non validi e fonti di comportamento indefinito". Questo è il motivo per cui penso che questo tipo di domanda dovrebbe fungere da suggerimento per considerare altre lingue. Ha dei buchi UB che non possono essere risolti senza adottare un approccio di base diverso.
Daniel Earwicker,
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.