Ein mutable
Feld kann auch in einem Objekt geändert werden, auf das über einen const
Zeiger oder eine Referenz zugegriffen wird , oder in einem const
Objekt, sodass der Compiler weiß, dass es nicht im R / O-Speicher gespeichert werden soll. Ein volatile
Speicherort kann durch Code geändert werden, den der Compiler nicht kennt (z. B. einen Treiber auf Kernelebene), sodass der Compiler z. B. die Registerzuweisung dieses Werts unter der ungültigen Annahme, dass der Wert "möglicherweise nicht haben kann", nicht optimieren kann geändert "seit es zuletzt in dieses Register geladen wurde. Dem Compiler werden sehr unterschiedliche Arten von Informationen gegeben, um sehr unterschiedliche Arten ungültiger Optimierungen zu stoppen.
volatile
Objekte können auch durch Prozesse geändert werden, an denen die CPU überhaupt nicht beteiligt ist. Beispielsweise kann sich ein von Bytes empfangenes Register in einem Kommunikationsperipheriegerät beim Empfang eines Bytes inkrementieren (und dies kann sogar einen Interrupt auslösen). Ein weiteres Beispiel ist ein Register für anstehende Interrupt-Flags in einem Peripheriegerät.volatile
bedeutet nicht nur, dass sich das Objekt außerhalb des Wissens des Compilers ändern kann, sondern auch, dass Schreibvorgänge in das Objekt vom Compiler nicht entfernt werden können, selbst wenn diese Schreibvorgänge nutzlos erscheinen. Beispiel:x = 1; x = 0;
Wennx
es flüchtig ist, muss der Compiler beide Schreibvorgänge ausführen (die auf Hardwareebene von Bedeutung sein können). Für ein nichtflüchtiges Objekt könnte sich der Compiler jedoch dafür entscheiden, das nicht zu schreiben,1
da es nie verwendet wird.const
undvolatile
! Sie können das Objekt nicht ändern, aber es kann hinter Ihrem Rücken geändert werden.mutable
: Das veränderbare Schlüsselwort überschreibt alle einschließenden const-Anweisungen. Ein veränderbares Mitglied eines const-Objekts kann geändert werden.volatile
: Das Schlüsselwort volatile ist ein implementierungsabhängiger Modifikator, der beim Deklarieren von Variablen verwendet wird und den Compiler daran hindert, diese Variablen zu optimieren. Volatile sollte mit Variablen verwendet werden, deren Wert sich auf unerwartete Weise ändern kann (z. B. durch einen Interrupt), was zu Konflikten mit Optimierungen führen kann, die der Compiler möglicherweise durchführt.Quelle
quelle
Volatile should be used with variables whose value can change in unexpected ways
sollten wir es vorziehen, es zufällig zu verwenden?Sie sind definitiv nicht dasselbe. Mutable interagiert mit const. Wenn Sie einen const-Zeiger haben, können Sie normalerweise keine Mitglieder ändern. Mutable bietet eine Ausnahme von dieser Regel.
Volatile hingegen hat nichts mit Änderungen zu tun, die vom Programm vorgenommen wurden. Dies bedeutet, dass sich der Speicher aus Gründen ändern kann, die außerhalb der Kontrolle des Compilers liegen. Daher muss der Compiler die Speicheradresse jedes Mal lesen oder schreiben und kann den Inhalt nicht in einem Register zwischenspeichern.
quelle
T
, in einem speichernconst T*
und daraus lesen. Wenn Sie dieses Objektvolatile
erstellen, schlägt das Speichern seiner Adresseconst T*
fehl, obwohl Sie nie versuchen zu schreiben.volatile
und Änderungen / Modifikationen / Speicherschreibvorgänge aus dem Programmcode sind vollständig orthogonal.Eine grobe, aber effektive Art, über den Unterschied nachzudenken, ist:
quelle
volatile
bytes_received,mutable
reference_count.Eine markierte Variable
mutable
ermöglicht das Ändern in einer deklarierten Methodeconst
.Eine markierte Variable
volatile
teilt dem Compiler mit, dass er die Variable jedes Mal lesen / schreiben muss, wenn Ihr Code dies ebenfalls mitteilt (dh er kann den Zugriff auf die Variable nicht optimieren).quelle
Ich möchte hinzufügen, dass flüchtig auch sehr nützlich ist, wenn es um Multithreading-Anwendungen geht, dh Sie haben Ihren Hauptthread (wo main () lebt) und Sie erzeugen einen Arbeitsthread, der sich weiter dreht, während eine Variable "app_running" wahr ist. main () steuert, ob "app_running" wahr oder falsch ist. Wenn Sie also das flüchtige Attribut nicht zur Deklaration von "app_running" hinzufügen, optimiert der Compiler den Zugriff auf "app_running" im Code, der vom sekundären Thread main ( ) ändert möglicherweise "app_running" in "false", der sekundäre Thread wird jedoch weiterhin ausgeführt, da der Wert zwischengespeichert wurde. Ich habe das gleiche Verhalten mit gcc unter Linux und VisualC ++ gesehen. Ein "flüchtiges" Attribut in der "app_running" -Deklaration löste das Problem. So,
quelle