2010-03-15 14 views
75

Ho una domanda sulla differenza tra volatile e mutabile. Ho notato che entrambi i due significano che potrebbe essere cambiato. Cos'altro? Sono la stessa cosa? Qual è la differenza? Dove sono applicabili? Perché le due idee sono proposte? Come usarli in modo diverso?volatile vs. mutabile in C++

Grazie mille.

risposta

96

Un campo mutable può essere modificata anche in un oggetto accessibile tramite un puntatore const o riferimento, o in un oggetto const, quindi il compilatore sa di non riporre nella memoria R/O. A volatile la posizione è quella che può essere modificata dal codice di cui il compilatore non è a conoscenza (ad esempio un driver a livello di kernel), quindi il compilatore non sa di ottimizzare ad es. registrare l'assegnazione di quel valore sotto l'assunto non valido che il valore "non può essere cambiato" dal momento in cui è stato caricato l'ultima volta in quel registro. Tipo di informazioni molto diverso da dare al compilatore per bloccare tipi molto diversi di ottimizzazioni non valide.

+12

Gli oggetti 'volatile' possono anche essere modificati da processi che non coinvolgono la CPU. Ad esempio, un registro ricevuto da un byte in una periferica di comunicazione può incrementare se stesso sulla ricezione di un byte (e questo può anche attivare un interrupt). Un altro esempio è un flag di interrupt in attesa di registrazione in una periferica. –

+48

Inoltre, 'volatile' non significa solo che l'oggetto può cambiare al di fuori della conoscenza del compilatore, ma significa anche che le scritture sull'oggetto non possono essere eliminate dal compilatore anche se tali scritture sembrano essere inutili. Ad esempio: 'x = 1; x = 0; 'se' x' è volatile, il compilatore deve emettere entrambe le operazioni di scrittura (che potrebbero essere significative a livello di hardware). Tuttavia, per un oggetto non volatile, il compilatore può scegliere di non preoccuparsi di scrivere il '1' poiché non viene mai utilizzato. –

+11

Un oggetto può essere contrassegnato sia 'const' che' volatile'! Non puoi cambiare l'oggetto, ma può essere cambiato dietro le tue spalle. – CTMacUser

21

Non sono assolutamente la stessa cosa. Mutevole interagisce con const. Se si dispone di un puntatore const, normalmente non è possibile modificare i membri. Mutable fornisce un'eccezione a questa regola.

Volatile, d'altra parte, non ha alcun rapporto con le modifiche apportate dal programma. Significa che la memoria potrebbe cambiare per ragioni che sfuggono al controllo del compilatore, quindi il compilatore deve leggere o scrivere l'indirizzo di memoria ogni volta e non può memorizzare nella cache il contenuto di un registro.

+0

* "Volatile, d'altra parte, non è completamente correlato alle modifiche apportate dal programma ..." * - hmmm, rendere un membro volatile e vedere quali interruzioni durante la compilazione. Cercare di aggiungere volatile dopo il fatto è un po 'come cercare di aggiungere const dopo il fatto ... Doloroso. – jww

+0

@jww: È totalmente estraneo alle scritture fatte dal programma. Puoi prendere l'indirizzo di un oggetto di tipo 'T', e memorizzarlo in un' const T * 'e leggere da esso. Se rendi quell'oggetto 'volatile', la memorizzazione del suo indirizzo in' const T * 'fallirà, anche se non stai mai provando a scrivere. 'volatile' e le modifiche/modifiche/scritture di memoria dal codice del programma sono completamente ortogonali. –

25

mutable: la parola chiave mutabile sovrascrive qualsiasi istruzione const acclusa. Un membro mutabile di un oggetto const può essere modificato.

volatile: la parola chiave volatile è un modificatore dipendente dall'implementazione, utilizzato durante la dichiarazione delle variabili, che impedisce al compilatore di ottimizzare tali variabili. Volatile dovrebbe essere usato con variabili il cui valore può cambiare in modi imprevisti (cioè attraverso un interrupt), che potrebbe entrare in conflitto con le ottimizzazioni che il compilatore potrebbe eseguire.

Source

+0

hai detto che "Volatile dovrebbe essere usato con variabili il cui valore può cambiare in modi imprevisti" dovremmo preferirlo usarlo con random? – UnKnown

7

Una variabile contrassegnata con mutable consente di modificarla in un metodo dichiarato const.

Una variabile contrassegnata con volatile indica al compilatore che deve leggere/scrivere la variabile ogni volta che il codice lo indica anche (cioè non è possibile ottimizzare gli accessi alla variabile).

13

Un modo rozzo ma efficace del pensiero della differenza è:

  • Il compilatore sa quando un oggetto cambia mutevoli.
  • Il compilatore non può sapere quando un oggetto volatile cambia.
+1

In questo senso: 'volatile' bytes_received,' mutable' reference_count. –

4

vorrei aggiungere che volatili è anche molto utile quando si tratta di applicazioni multithreading, vale a dire, hai il tuo thread principale (dove main() vive) e si spawn un thread di lavoro che manterrà filatura mentre una variabile "app_running" è vero. main() controlla se "app_running" è vero o falso, quindi se non si aggiunge l'attributo volatile alla dichiarazione di "app_running", se il compilatore ottimizza l'accesso a "app_running" nel codice eseguito dal thread secondario, main () potrebbe cambiare "app_running" in false ma il thread secondario continuerà a essere eseguito perché il valore è stato memorizzato nella cache. Ho visto lo stesso comportamento usando gcc su Linux e VisualC++. Un attributo "volatile" inserito nella dichiarazione "app_running" ha risolto il problema.Quindi, questo è uno scenario in cui non vengono interrotti hardware o kernel nel modificare il valore di tali variabili.

+0

No! Questo è un malinteso comune. C++ 11 e C11 hanno introdotto l'atomica per questo scopo http://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model – KristianR