Differenza tra immutabile e const


28

Ho visto spesso i termini immutablee constusato in modo intercambiabile. Tuttavia, dalla mia (piccola) esperienza, i due differiscono molto nel "contratto" che compongono nel codice:

Immutabile rende il contratto che questo oggetto non cambierà, in alcun modo (es. Tuple Python, stringhe Java).

Const stipula il contratto che nell'ambito di questa variabile non verrà modificato (nessuna promessa su ciò che altri thread potrebbero fare sull'oggetto indicato durante questo periodo, ad esempio la parola chiave C / C ++).

Ovviamente, i due non sono equivalenti, a meno che il linguaggio non sia a thread singolo (PHP) o non abbia un sistema di tipizzazione lineare o uniquness (Clean, Mercury, ATS).

Innanzitutto, la mia comprensione di questi due concetti è corretta?

Secondo, se c'è una differenza, perché vengono usati quasi esclusivamente in modo intercambiabile?


1
constnon esiste in tutte le lingue e la mutabilità e l'immutabilità non esistono in tutte le lingue, quindi rendere questa lingua agonistica non è applicabile. È specifico della lingua solo dove si applicano questi concetti.

2
Lettura correlata, raccomandata: Kinds of Immutability (alcuni esempi in C #, ma in gran parte indipendente dal linguaggio). Qualcuno dà una medaglia a Eric Lippert.

Risposte:


14

Parlerò in C ++, dove questa differenza è più rilevante.

Come noterai correttamente, immutabile significa che un oggetto non può cambiare affatto dopo la sua creazione. Questa creazione può ovviamente avvenire in fase di esecuzione, ovvero un constoggetto non è necessariamente una costante di compilazione. In C ++, un oggetto è immutabile se sono soddisfatti (1) e (2) o (3):

  1. Non ha membri dichiarati mutablemutati dalle constfunzioni dei membri

  2. È dichiarato const

  3. constle funzioni membro non vengono utilizzate const_castper rimuovere la constqualifica al fine di mutare qualsiasi membro

Tuttavia, potresti anche prendere in considerazione i modificatori di accesso: se un'operazione muta internamente un'istanza, ma non ha alcun effetto sullo stato dell'istanza osservabile attraverso la sua interfaccia pubblica, l'oggetto è "logicamente immutabile".

Quindi C ++ fornisce gli strumenti necessari per creare oggetti immutabili, ma come la maggior parte di tutto in C ++, gli strumenti sono solo minimamente sufficienti e richiedono diligenza per essere effettivamente utilizzati. Lo stato di un'istanza non è necessariamente limitato alle variabili dei membri dell'istanza, poiché C ++ non fornisce un modo per applicare la trasparenza referenziale, ma può includere anche lo stato globale o di classe.

constha anche un'altra funzione in C ++: qualificare riferimenti e puntatori. Un constriferimento può riferirsi a un non constoggetto. È legale (anche se generalmente non necessario o consigliabile) utilizzare const_castper mutare un oggetto attraverso un constriferimento, se e solo se l' oggetto è dichiarato non const:

int        i = 4;         // Non-const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Legal.

E ovviamente è un comportamento indefinito mutare un constoggetto:

const int  i = 4;         // const object.
const int* p = &i;        // const pointer.

*const_cast<int*>(p) = 5; // Illegal.

19

Parlando per Java dove la parola chiave "final" rappresenta "const", considera:

final Person someone = new Person();

Questo significa che someonenon può MAI fare riferimento a un altro oggetto Person. Tuttavia, è ancora possibile modificare i dettagli della persona a cui si fa riferimento. Per esempiosomeone.setMonthlySalary(10000);

Ma, se someonefosse un oggetto "Immutabile", una delle seguenti sarebbe vera: (a) Non avresti un metodo chiamato setMonthlySalary (b) Chiamare setMonthlySalary genererebbe sempre un'eccezione comeUnsupportedOperationException


10

Gli oggetti immutabili sono quelli che non cambiano stato dopo averlo creato. Per esempio;

string prefix = "Pre";
string postfix = "Post";
string myComplexStr = prefix + postfix;

In questo esempio l'oggetto myComplexStr è immutabile ma non costante perché viene calcolato il valore. Ed è immutabile perché è una stringa e ha una proprietà di lunghezza statica e non può cambiare.

Gli oggetti Const vengono generalmente utilizzati per identificare alcune costanti reali i cui valori sono noti prima della compilazione come Pi, "USA", "StackOverflow.com", numeri di porta e così via.

Da questo punto di vista Cost è diverso dagli oggetti Immutabili perché i loro valori non sono calcolati dal programma.

Ma se stai parlando della parola chiave "const" in C ++, puoi dire che "const" è usato per creare oggetti immutabili.


1
const in C ++ non crea oggetti immutabili, è solo un livello di accesso.
Klaim,

Puoi spiegare come "const double pi = 3.14" non sia immutabile?
Mert Akcakaya,

Bene dipende da dove si trova. Diciamo che lo faccio: "double * p_pi = const_cast <double *> (& pi); * p_pi = 42;" per esempio. Quindi se pi è nello spazio globale o nello spazio dei nomi, ottengo un errore di segmentazione, ma credo che sia un comportamento indefinito, non un errore specifico. Se pi è un membro di qualsiasi oggetto disponibile in fase di runtime, che non è statico, ottengo pi == 42. Vedete, anche l'uso di mutable è disponibile perché const in C ++ riguarda il livello di accesso, semantico, non l'immutabilità dei dati, che è quasi impossibile da ottenere in C ++. Puoi solo "simularlo". const non è immutabile.
Klaim,

1
@Klaim La mutazione di un constsimile è un comportamento indefinito, indipendentemente da dove è allocata, IIRC. E il comportamento indefinito è peggiore di qualsiasi errore specifico garantito. Significa che non usi più C ++ - C ++ non fornisce alcun mezzo per modificare un constvalore (tranne i mutablemembri ovviamente, ma non è questo il punto), quindi per quanto riguarda C ++, non puoi farlo. Ciò che le implementazioni specifiche sono consentite è completamente un'altra cosa (e scommetto che, se si compila con ottimizzazioni, l'acrobazia che hai fatto non influirà sulle espressioni successive usando piperché è stata sostituita).

"const in C ++ non crea oggetti immutabili" è ancora sbagliato perché crea ancora costanti globali come hai affermato nella tua risposta. La parola chiave è naturalmente semantica a un certo livello, altrimenti potresti sempre cambiare manualmente la tensione di una cella di memoria e cambiare il valore di un oggetto immutabile se sei così ansioso di usare anche comportamenti indefiniti.
Mert Akcakaya,

8

Innanzitutto, la mia comprensione di questi due concetti è corretta?

Sì, ma la tua seconda domanda mostra che non capisci queste differenze.

Secondo, se c'è una differenza, perché vengono usati quasi esclusivamente in modo intercambiabile?

constin C ++ viene utilizzato solo per il livello di accesso (significa "sola lettura") , non per l'immutabilità. Implica che l'accesso stesso sia totalmente separato dai dati. Ad esempio, è possibile manipolare alcuni dati, quindi esporli attraverso un riferimento const. L'accesso è di sola lettura, ma i dati stessi, poiché tutti i datam sono mutabili.

const garantisce solo limitazioni di accesso, mentre l' immutabilità (come in D ad esempio) non implica in realtà alcun modo di modificare i dati in qualunque fase della vita dell'oggetto .

Ora, puoi simulare l'immutabilità in C ++ assicurandoti che alcuni dati non siano accessibili in altro modo che const e assicurati che siano inizializzati e non toccati più. Ma questa non è una forte garanzia come lingue come D ti danno quando i tuoi dati sono immutabili. Il linguaggio si assicura che non sia affatto possibile eseguire alcuna operazione di modifica di tali dati, mentre in C ++ si è ancora potenzialmente in grado di modificare i dati attraverso il cast di const e la mutabilità, se necessario.

Alla fine, non è affatto lo stesso in quanto non offre affatto le stesse garanzie.


3

Parlando di JavaScript, le parole chiave consteObject.freeze

constsi applica agli attacchivariables . Crea un'associazione immutabile, non puoi assegnargli un nuovo valore.

Object.freezefunziona sui valori degli oggetti. Rende immutabile un oggetto . Vale a dire, non è possibile modificarne le proprietà.


0

In C ++ sono gli stessi. Sebbene sia possibile modificare un constoggetto se si dispone della posizione in memoria e dell'autorizzazione del sistema operativo per scrivere in tale memoria.


1
In realtà questo è un argomento contro il fatto che siano uguali: C ++ semplicemente non ha parole chiave o linguaggio linguistici immutabili. Inoltre, suppongo che il programmatore utilizzi la lingua in modo sano: altrimenti anche const non ha assolutamente alcun valore.
K.Steff,

1
@ K.Steff - forse meglio dire che non vi è alcuna immutabilità in C ++ oltre a quella fornita da const
Martin Beckett

Assolutamente preciso :)
K.Steff,

In C ++ non sono affatto gli stessi. const è un livello di accesso di "sola lettura", non significa che i dati siano immutabili. Puoi bypassarlo in C ++, il più delle volte.
Klaim,

0

In C, C ++ e nei linguaggi correlati, esiste anche una differenza tra un oggetto const e il riferimento o il puntatore all'oggetto come riferimento costante.

Se si tenta di modificare un oggetto costante, si ottiene un comportamento indefinito. (Puoi provare a modificare un oggetto costante, ad esempio prendendo il suo indirizzo, lanciando l'indirizzo su un puntatore non const e quindi usando quel puntatore non const per modificare l'oggetto).

Il puntatore o riferimento costante d'altra parte dice semplicemente al compilatore che non è possibile utilizzare questo puntatore o riferimento per modificare l'oggetto. È possibile eseguire il cast del puntatore o riferimento e provare a modificare l'oggetto. Se l'oggetto stesso fosse costante, succederanno cose brutte. Se l'oggetto non era effettivamente costante, cambierà. Questo può ovviamente confondere gli utenti del tuo codice e molto probabilmente causare bug.

In C, se usi una stringa letterale come "Hello", i cinque caratteri e i byte zero finali sono effettivamente costanti, ma ottieni un puntatore non const. Pessima idea di usare quel puntatore non const per cambiare l'oggetto.

In C, puoi avere un puntatore "const limit". Ciò significa che l'oggetto indicato è temporaneamente costante. Se l'oggetto viene modificato in qualsiasi modo mentre il puntatore "const limit" è nell'ambito, si ottiene un comportamento indefinito. Questo è più forte di un puntatore const che ti impedisce solo di cambiare un oggetto attraverso questo puntatore.

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.