Tutti gli oggetti in C ++ sono mutabili se non diversamente specificato?

6

Tutti gli oggetti in C ++ sono mutabili se non diversamente specificato?

In Python e Javascript non posso cambiare stringhe, tuple, unicodes. Mi chiedevo se c'è qualcosa in C ++ che è immutabile o ogni oggetto è mutabile e devo usare const qualificatore di tipo per renderlo immutabile.

    
posta G M 10.01.2017 - 10:28
fonte

3 risposte

18

L'immutabilità è stata ben compresa da tempo. Python, Java e C ++ hanno diversi modelli di memoria che rendono difficili i confronti diretti. L'autore del articolo che hai citato in origine non sembra sapere C ++.

Come in Python, Java e nella maggior parte dei linguaggi multi-paradigma, C e C ++ consentono la mutabilità per impostazione predefinita. Questo è quello che di solito i programmatori vogliono: se ho una variabile String x , voglio poter assegnare un nuovo valore x = "foo" .

Il sistema const in C e C ++ consente una grande quantità di immutabilità sfumata che manca in Python, Java e persino in Scala. Se una funzione C ++ accetta un const std::string& o un const char* , promette (e il compilatore garantisce, in una certa misura), che questa funzione non modificherà (non può!) Il contenuto di quella stringa. Dato un oggetto const, possiamo solo invocare metodi di quell'oggetto che sono anche marcati come const. Se una classe C ++ ha solo membri pubblici che sono const , allora l'oggetto è effettivamente immutabile.

Tuttavia, questo a volte confonde poiché gli oggetti C e C ++ sono posizioni di memoria e le variabili sono nomi per le posizioni di memoria. Al contrario, le variabili in Python e Java sono nomi per i puntatori agli oggetti. In una lingua con semantica di riferimento, x = y significa "marca x punta allo stesso oggetto di y". Dato che stiamo solo copiando i puntatori, questo è possibile con oggetti immutabili. In una lingua con semantica del valore come C ++, significa "aggiorna il contenuto di x con il contenuto di y ". Pertanto, se si desidera la riassegnazione di una variabile in C o C ++, la variabile potrebbe non avere un tipo const. Per fare ciò con oggetti immutabili, dovremmo usare un puntatore in modo esplicito.

Che Java e Python utilizzino oggetti stringa immutabili è una decisione progettuale fondamentale, ma non è direttamente collegata ai vantaggi dell'immutabilità in un ambiente multithreading. Una ragione è che i valori letterali delle stringhe nel codice sorgente possono essere raggruppati, riducendo il numero di oggetti. Questo è possibile anche in C / C ++. In C ++ il letterale "foo" ha tipo const char[4] (il quarto carattere è il% co_de terminante). Un altro motivo è che le voci nei set e nelle chiavi in dicts / maps non devono essere modificate. Poiché le stringhe sono usate in modo pervasivo come le chiavi dict (la maggior parte degli oggetti Python sono un ditt), l'immutabilità rimuove una fonte comune di errori. In Java, un altro motivo per le stringhe immutabili è il modello di sicurezza Java. Tutti questi motivi sono del tutto estranei al multithreading.

Se Java fosse stato costruito pensando all'immutabilità, il linguaggio sarebbe stato molto diverso. Sebbene sia strettamente ispirato al C ++, i progettisti hanno provato a creare un linguaggio molto più semplice, eliminando cost è un passo del genere. La cosa equivalente di Java a un riferimento const C ++ è un adattatore o un decoratore che implementa qualsiasi metodo di muting come 'throws new NotImplementedException()' e inoltra chiamate di metodo non mutanti alla raccolta effettiva. Il fatto che le interfacce di raccolta java.util implichino tutte la mutabilità è un chiaro segno del fatto che non si sono battuti per una prima lingua di immutabilità.

La soluzione Java proposta per risolvere i problemi di concorrenza non era immutabilità, ma blocco pervasivo. Ogni singolo oggetto contiene un mutex che può essere usato per synchronized blocchi o interi metodi. A quanto pare, ciò non va bene per le prestazioni, non ha una scala molto buona, ed è abbastanza incline agli errori - devi ancora affrontare lo stato globale mutevole.

    
risposta data 10.01.2017 - 11:57
fonte
9

Quasi. Il linguaggio stesso considera tutto come mutabile a meno che non si usi const , ma è ancora possibile creare oggetti immutabili senza dire al compilatore che sono immutabili, semplicemente non fornendo un modo per mutarli.

Ad esempio, prendi questa classe:

class MyClass {
    int value;
public:

    MyClass(int v) : value(v) {}
    int getValue() {return value;}

    MyClass &operator=(const MyClass &other) = delete;
};

Le istanze di MyClass sono immutabili, perché non c'è modo di mutarle - ma in nessuna parte del codice è in realtà dichiarato che sono immutabili. (Questo è lo stesso modo in cui le istanze della classe String di Java sono immutabili)

    
risposta data 10.01.2017 - 11:55
fonte
2

No, c'è un'eccezione: Lambdas e per estensione gli oggetti che catturano sono immutabili per impostazione predefinita:

int i = 0;

[i]{//capturing the value i
    i++; //does not compile, i is const
};

[i]() mutable{ //make the lambda mutable
    i++; //compiles fine
};

Quindi, anziché aggiungere const per renderlo immutabile, aggiungi mutable per renderlo non const .

    
risposta data 10.01.2017 - 17:31
fonte

Leggi altre domande sui tag