93

I have a question about the difference between volatile and mutable. I noticed that both of the two means that it could be changed. What else? Are they the same thing? What's the difference? Where are they applicable? Why the two ideas are proposed? How to use them in different way?

Thanks a lot.

Alex Bitek
  • 6,529
  • 5
  • 47
  • 77
skydoor
  • 25,218
  • 52
  • 147
  • 201

6 Answers6

121

A mutable field can be changed even in an object accessed through a const pointer or reference, or in a const object, so the compiler knows not to stash it in R/O memory. A volatile location is one that can be changed by code the compiler doesn't know about (e.g. some kernel-level driver), so the compiler knows not to optimize e.g. register assignment of that value under the invalid assumption that the value "cannot possibly have changed" since it was last loaded in that register. Very different kind of info being given to the compiler to stop very different kinds of invalid optimizations.

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 14
    `volatile` objects could also be changed by processes not involving the CPU at all. For example, a bytes-received register in a communications peripheral can increment itself on the receipt of a byte (and this can even trigger an interrupt). Another example is a pending-interrupts flags register in a peripheral. – Mike DeSimone Mar 15 '10 at 03:22
  • 58
    Also, `volatile` doesn't only mean that the object can change outside the compiler's knowledge - it also means that writes to the object can't be eliminated by the compiler even if those writes appear to be useless. For example: `x = 1; x = 0;` if `x` is volatile, the compiler has to emit both write operations (which might be significant at the hardware level). However, for a non-volatile object, the compiler could chose not to bother with writing the `1` since it's never used. – Michael Burr Mar 15 '10 at 03:34
  • 17
    An object can be marked both `const` and `volatile`! You can't change the object, but it can be changed behind your back. – CTMacUser May 25 '13 at 10:08
  • @MichaelBurr: Why compiler has to emit both write operations ? How it might be significant at the hardware level ? – Destructor May 07 '16 at 05:37
  • 2
    @Destructor: the usual situation is for writes to a hardware device register. – Michael Burr May 07 '16 at 08:38
  • 6
    @Destructor let's say you are controlling the status of an LED. Write 0 turns it OFF, write 1 turns it ON. If I need to flash the LED to communicate some error status, but the compiler decides to optimize out all the writes except the last one, since none of the values are being used, then the LED never flashes and the behavior I desire is not realized. – iheanyi May 23 '17 at 16:57
  • I don't know What `so the compiler knows not to stash it in R/O memory` means...... – SungJinKang May 09 '21 at 06:08
28

mutable: The mutable keyword overrides any enclosing const statement. A mutable member of a const object can be modified.

volatile: The volatile keyword is an implementation-dependent modifier, used when declaring variables, which prevents the compiler from optimizing those variables. Volatile should be used with variables whose value can change in unexpected ways (i.e. through an interrupt), which could conflict with optimizations that the compiler might perform.

Source

xian
  • 4,657
  • 5
  • 34
  • 38
  • you said `Volatile should be used with variables whose value can change in unexpected ways` should we prefer to use it with random? – Asif Mushtaq Jun 10 '15 at 07:07
  • @AsifMushtaq not values. ways. mutable effects the permisions the code you write has. So you can access the variable via a const ptr, or const reference. What if its not your code changing it? Something the compiler cant check the ptr or reference type of? Thats volatile. And volatile also forces the cache write back to main memory. So this is used a LOT with multi threaded code. :) – Dan Nov 15 '19 at 22:25
23

They are definitely NOT the same thing. Mutable interacts with const. If you have a const pointer, you normally could not change members. Mutable provides an exception to that rule.

Volatile, on the other hand, is totally unrelated to changes made by the program. It means that the memory could change for reasons beyond the control of the compiler, therefore the compiler has to read or write the memory address every time and can't cache the content in a register.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • *"Volatile, on the other hand, is totally unrelated to changes made by the program..."* - hmmm, make a member volatile and see what breaks during the compile. Trying to add volatile after the fact is a lot like trying to add const after the fact... Painful. – jww Nov 15 '15 at 20:16
  • @jww: It's totally unrelated to writes made by the program. You can take the address of an object of type `T`, and store it into a `const T*` and read from it. If you make that object `volatile`, storing its address into `const T*` will fail, even though you are never trying to write. `volatile` and changes / modifications / memory writes from program code are completely orthogonal. – Ben Voigt Nov 15 '15 at 20:41
19

A crude but effective way of thinking of the difference is:

  • The compiler knows when a mutable object changes.
  • The compiler cannot know when a volatile object changes.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
11

A variable marked mutable allows for it to be modified in a method declared const.

A variable marked volatile tells the compiler that it must read/write the variable every time your code tells it too (i.e. it cant optimize away accesses to the variable).

Kyle Lutz
  • 7,966
  • 2
  • 20
  • 23
5

I would like to add that volatile is also very useful when dealing with multithreading applications, i.e, you have your main thread (where main() lives) and you spawn a worker thread that will keep spinning while a variable "app_running" is true. main() controls whether "app_running" is true or false, so if you do not add the volatile attribute to the declaration of "app_running", if the compiler optimizes access to "app_running" in the code ran by the secondary thread, main() might change "app_running" to false but the secondary thread will keep running because the value has been cached. I have seen the same behavior using gcc on Linux and VisualC++. A "volatile" attribute put in "app_running" declaration solved the problem. So, this is scenario where no hardware interrupts or kernel is invoved in changing the value of such variables.

BinCoder
  • 59
  • 1
  • 1
  • 2
    No! This is a common misunderstanding. C++11 and C11 introduced atomics for this purpose http://stackoverflow.com/questions/8819095/concurrency-atomic-and-volatile-in-c11-memory-model – KristianR Apr 05 '14 at 15:33