2012-07-12 18 views
8

Dalla mia comprensione, mutable annulla la constness di una variabileconst_cast VS mutabile? qualche differenza?

Class A { 
    void foo() const { 
    m_a = 5; 
} 
mutable int m_a; 
}; 

Ma anche const_cast:

void print (char * str) 
{ 
    cout << str << endl; 
} 

int main() { 
    const char * c = "this is a line"; 
    print (const_cast<char *> (c)); 
    return 0; 
} 

Allora, che cosa cambia l'una dall'altra?

Grazie

risposta

16

const_cast impossibile annullare la costanza di un oggetto. const_cast può rimuovere solo la costanza da un percorso di accesso a un oggetto. Il percorso di accesso è un puntatore o un riferimento a un oggetto. La rimozione della costanza dal percorso di accesso non ha assolutamente alcun effetto sull'oggetto stesso. Anche se si utilizza const_cast per rimuovere la costanza del percorso di accesso, questo non ti dà necessariamente il permesso di modificare l'oggetto. Se puoi farlo o no dipende ancora dall'oggetto stesso. Se è const, non ti è permesso modificarlo e qualsiasi tentativo di farlo risulterà in un comportamento indefinito.

Ad esempio, questo illustra la destinazione d'uso const_cast

int i = 5; // non-constant object 
    const int *p = &i; // `p` is a const access path to `i` 

    // Since we know that `i` is not a const, we can remove constness... 
    int *q = const_cast<int *>(p); 
    // ... and legally modify `i` 
    *q = 10; 
    // Now `i` is 10 

L'unica ragione per quanto sopra è legale e valido è il fatto che i è in realtà un non costante oggetto , e sappiamo su di esso .

Se l'oggetto originale è stato davvero costante, quindi il codice riportato sopra dovrebbe produrre un comportamento indefinito:

const int j = 5; // constant object 
    const int *p = &j; // `p` is a const access path to `j` 

    int *q = const_cast<int *>(p); // `q` is a non-const access path to `j` 
    *q = 10; // UNDEFINED BEHAVIOR !!! 

linguaggio C++ non consente di modificare gli oggetti costanti ed const_cast è completamente impotente qui, a prescindere da come si usa esso.

mutable è una cosa completamente diversa. mutable crea un archivio dati che può essere modificato legalmente anche se l'oggetto contenitore è dichiarato const. In questo senso, mutable consente di modificare [alcune parti designate di] oggetti costanti. const_cast, d'altra parte, non può fare nulla del genere.

1

La differenza è semantica - i. e. stesso codice generato, stesso risultato in tempo di esecuzione (const ness è comunque un costrutto puramente in fase di compilazione), ma i due costrutti trasmettono un significato leggermente diverso.

L'idea è di utilizzare mutable per le variabili presenti nella classe, ma che non costituiscono lo stato dell'oggetto. L'esempio classico è la posizione corrente in un oggetto blob. Navigare nel blob non conta come "modificare" il blob in un modo che conta. Usando mutable, stai dicendo "questa variabile può cambiare, ma l'oggetto è sempre lo stesso". Stai affermando che per questa particolare classe, const -ness non significa "tutte le variabili sono congelate".

const_cast, al contrario, significa che stai violando la correttezza const esistente e sperare di farla franca. Probabilmente perché stai lavorando con un'API di terze parti che non rispetta lo const (ad esempio una vecchia scuola basata su C).

4

La differenza è che const_cast non può imbrogliare, ma mutable è un'eccezione alle regole.

Nel primo frammento m_a è mutable e quindi un'eccezione alla regola che non è possibile modificare i membri dati nelle funzioni membro const.

Al secondo frammento, const_cast cerca di imbrogliare, ma in realtà non può: mentre il tipo è cambiato, modifica effettiva non è permesso: la stringa è veramente const. Tentare di modificarlo causerebbe un comportamento indefinito del programma.

0

In poche parole, dichiarare una variabile membro come mutable lo rende accessibile in scrittura da qualsiasi metodo costante di quella classe senza alcuna altra sintassi speciale. const_cast deve invece essere eseguito ogni volta che si desidera accedere in scrittura a una variabile altrimenti costante e tale variabile non deve nemmeno essere un membro della classe.

A meno che non si desideri consentire esplicitamente l'accesso in scrittura a una variabile membro, è preferibile utilizzare const_cast in ogni caso di violazione della correttezza const, se non altro per indicare chiaramente le proprie intenzioni.

Nota a margine, const_cast può anche essere utilizzato per aggiungere o rimuovere il modificatore volatile.

Problemi correlati