556

A while ago I came across some code that marked a member variable of a class with the mutable keyword. As far as I can see it simply allows you to modify a variable in a const method:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

Is this the only use of this keyword or is there more to it than meets the eye? I have since used this technique in a class, marking a boost::mutex as mutable allowing const functions to lock it for thread-safety reasons, but, to be honest, it feels like a bit of a hack.

M4N
  • 90,223
  • 44
  • 210
  • 255
Rob
  • 70,036
  • 53
  • 151
  • 189

18 Answers18

376

It allows the differentiation of bitwise const and logical const. Logical const is when an object doesn't change in a way that is visible through the public interface, like your locking example. Another example would be a class that computes a value the first time it is requested, and caches the result.

Since c++11 mutable can be used on a lambda to denote that things captured by value are modifiable (they aren't by default):

int x = 0;
auto f1 = [=]() mutable {x = 42;};  // OK
auto f2 = [=]()         {x = 42;};  // Error: a by-value capture cannot be modified in a non-mutable lambda
yuri kilochek
  • 11,212
  • 2
  • 25
  • 52
KeithB
  • 15,563
  • 2
  • 37
  • 44
  • 55
    'mutable' does not affect bitwise/logical constness at all. C++ is *only* bitwise const and the 'mutable' keyword can be used to exclude members from this checking. It is not possible to achieve 'logical' const in C++ other than via abstractions (eg. SmartPtrs). – Richard Corden Sep 22 '08 at 08:13
  • 123
    @Richard: you're missing the point. There is no "logical const" keyword, true, rather, it's a conceptual differentiation the programmer makes to decide which members should be excluded by being made mutable, based on an understanding of what constitutes the logical observable state of the object. – Tony Delroy Jul 29 '11 at 02:11
  • 2
    I think @Richard's comment is valuable in that it helps clarify KeithB's explanation with some more detail. At least it helped me :) – scorpiodawg Sep 19 '11 at 20:48
  • 2
    Both KeithB and @RichardCorden are correct, depending on perspective. Were the terms used by KeithB more rigorously defined, there would be no ambiguity (and probably no disagreement); but the ambiguity does not interfere with the value of KeithB's answer, in my opinion - it's a valuable answer, and a correct one, I think. – Dan Nissenbaum May 29 '12 at 05:09
  • 1
    can we change mutable data members of a const object.? – null Mar 06 '13 at 13:27
  • 6
    @ajay Yes, that is the whole point of markig a member variable as mutable, to allow it to be changed in const objects. – KeithB Mar 06 '13 at 14:48
  • 7
    Why does one need mutable on lambdas? Wouldn't it suffice to capture variable by reference? – Giorgio Apr 24 '13 at 11:02
  • 14
    @Giorgio: The difference is that the modified `x` within the lambda remains within the lambda, i.e. the lambda function can only modify its own copy of `x`. The change is not visible outside, the original `x` is still unchanged. Consider that lambdas are implemented as functor classes; captured variables correspond to member variables. – Sebastian Mach Jun 05 '13 at 15:28
  • @phresnel: OK, then I do not understand why captured variables (member variables that are copies of variables from the context) are const by default. Is there a particular reason for this? – Giorgio Jun 05 '13 at 15:37
  • 1
    "Logical const is when an object doesn't change in a way that is visible through the public interface, like your locking example.": In what sense using a mutex does not change the observable behaviour of an object? The next time a locking method is invoked by another thread, the method will stop and wait until the thread holding the lock exits the locking method. This looks like an observable change of behaviour to me. – Giorgio Jun 05 '13 at 15:46
  • @Giorgio: Maybe my new Q/A helps a bit: http://stackoverflow.com/questions/16944894/c-lambda-difference-between-mutable-and-capture-by-reference/16944895#16944895 – Sebastian Mach Jun 05 '13 at 16:16
  • 6
    @Giorgio, let's say I have a toaster and I place it in a room. When people want to use the toaster, you enter the room and lock the door. When you're done, you unlock the door and exit the room (door can only be locked/unlocked from the inside). Say I gain access to the room, lock the door, and use the toaster. You want to use the toaster. But the door is locked. Has the observable behavior of the toaster changed? No. Toaster still holds only two pieces of bread. Still converts raw bread into toast. Gaining access to the toaster isn't part of the toaster's behavior. – iheanyi Jun 05 '14 at 18:58
  • 5
    @iheanyi Excellent analogy, wittily delivered. And eerily apt, since the other day, having to take a break from fruitless debugging - which would later be shown to be related to threading, _no less_ - I thought I'd relax with some toasted potato scones (yeah, that's what I'm talking about). Instead, I blew the circuit breaker. Considering what preceded this attempt, I have no idea why I was mildly surprised! I guess my toaster wasn't thread safe either. – underscore_d Feb 15 '16 at 21:01
  • 1
    why bother using `mutable` when removing `const` enables mutability? Isn't overriding `constness` a bad thing in the first place? – Mushy Oct 18 '17 at 17:32
  • 1
    @Mushy using `const` keyword implies a constness from the perspective of the user of the class. If I initialise c1 and c2 as `const MyCls c1(); const MyCls c2 = c1;` then in any part of the code from there onwards, `c1 == c2` must always be true. Since equality is defined by the class itself, it can choose which members to use for equality check. Hence (for eg.) if it decides only to use public members for this check, then it can make private variables as mutable as this does not change the constness of the object and may also help the object for its internal workings. – Sourav Kannantha B Feb 14 '21 at 14:25
150

The mutable keyword is a way to pierce the const veil you drape over your objects. If you have a const reference or pointer to an object, you cannot modify that object in any way except when and how it is marked mutable.

With your const reference or pointer you are constrained to:

  • only read access for any visible data members
  • permission to call only methods that are marked as const.

The mutable exception makes it so you can now write or set data members that are marked mutable. That's the only externally visible difference.

Internally those const methods that are visible to you can also write to data members that are marked mutable. Essentially the const veil is pierced comprehensively. It is completely up to the API designer to ensure that mutable doesn't destroy the const concept and is only used in useful special cases. The mutable keyword helps because it clearly marks data members that are subject to these special cases.

In practice you can use const obsessively throughout your codebase (you essentially want to "infect" your codebase with the const "disease"). In this world pointers and references are const with very few exceptions, yielding code that is easier to reason about and understand. For a interesting digression look up "referential transparency".

Without the mutable keyword you will eventually be forced to use const_cast to handle the various useful special cases it allows (caching, ref counting, debug data, etc.). Unfortunately const_cast is significantly more destructive than mutable because it forces the API client to destroy the const protection of the objects (s)he is using. Additionally it causes widespread const destruction: const_casting a const pointer or reference allows unfettered write and method calling access to visible members. In contrast mutable requires the API designer to exercise fine grained control over the const exceptions, and usually these exceptions are hidden in const methods operating on private data.

(N.B. I refer to to data and method visibility a few times. I'm talking about members marked as public vs. private or protected which is a totally different type of object protection discussed here.)

Community
  • 1
  • 1
Dan L
  • 1,653
  • 1
  • 10
  • 7
  • 8
    Plus, using `const_cast` to modify a part of a `const` object yields undefined behaviour. – Brian Bi Apr 06 '15 at 00:25
  • 1
    I don't agree with _because it forces the API client to destroy the const protection of the objects_. If you were using `const_cast` to implement mutation of member variables in a `const` method, you wouldn't ask the client to the do the cast - you'd do it _within the method_ by `const_cast`ing `this`. Basically it lets you bypass constness on arbitrary members at a **specific call site**, while `mutable` let's you remove const on a **specific member** at all call sites. The latter is usually what you want for the typical use (caching, stats), but sometimes the const_cast fits the pattern. – BeeOnRope Jun 18 '17 at 22:39
  • 1
    The `const_cast` pattern does fit better in some cases, such as when you want to temporarily modify a member, then restore it (pretty much like `boost::mutex`). The method is logically const since the final state is the same as the initial, but you want to make that transient change. `const_cast` can be useful there because it lets you cast away const specifically in that method were you the mutation will be undone, but `mutable` wouldn't be as appropriate since it would remove const protection from _all_ methods, which don't necessarily all follow the "do, undo" pattern. – BeeOnRope Jun 18 '17 at 22:48
  • 3
    The possible placement of const _defined_ object into read-only memory (more generally, memory _marked_ read-only) and the associated standard language that allows this makes `const_cast` a possible time-bomb though. `mutable` has no such issue since such objects could not be placed in read-only memory. – BeeOnRope Jun 18 '17 at 22:54
77

Your use with boost::mutex is exactly what this keyword is intended for. Another use is for internal result caching to speed access.

Basically, 'mutable' applies to any class attribute that does not affect the externally visible state of the object.

In the sample code in your question, mutable might be inappropriate if the value of done_ affects external state, it depends on what is in the ...; part.

Frank Szczerba
  • 4,750
  • 3
  • 29
  • 30
36

Mutable is for marking specific attribute as modifiable from within const methods. That is its only purpose. Think carefully before using it, because your code will probably be cleaner and more readable if you change the design rather than use mutable.

http://www.highprogrammer.com/alan/rants/mutable.html

So if the above madness isn't what mutable is for, what is it for? Here's the subtle case: mutable is for the case where an object is logically constant, but in practice needs to change. These cases are few and far between, but they exist.

Examples the author gives include caching and temporary debugging variables.

John Millikin
  • 183,900
  • 37
  • 203
  • 216
  • 2
    I think this link gives the best example of a scenario where mutable is helpful.It almost appears they are exclusively used for debugging. (per correct usage) – enthusiasticgeek Jul 25 '12 at 14:08
  • The usage of `mutable` can make the code more readable and cleaner. In the following example, the `read` can be `const` as expected. ` mutable m_mutex; Container m_container; void add(Item item) { Lockguard lock(m_mutex); m_container.pushback(item); } Item read() const { Lockguard lock(m_mutex); return m_container.first(); } ` – Th. Thielemann Jan 07 '19 at 16:21
  • There's one extremely popular use case: ref counts. – Seva Alekseyev May 04 '20 at 20:10
35

It's useful in situations where you have hidden internal state such as a cache. For example:

class HashTable
{
...
public:
    string lookup(string key) const
    {
        if(key == lastKey)
            return lastValue;

        string value = lookupInternal(key);

        lastKey = key;
        lastValue = value;

        return value;
    }

private:
    mutable string lastKey, lastValue;
};

And then you can have a const HashTable object still use its lookup() method, which modifies the internal cache.

Adam Rosenfield
  • 360,316
  • 93
  • 484
  • 571
10

mutable does exist as you infer to allow one to modify data in an otherwise constant function.

The intent is that you might have a function that "does nothing" to the internal state of the object, and so you mark the function const, but you might really need to modify some of the objects state in ways that don't affect its correct functionality.

The keyword may act as a hint to the compiler -- a theoretical compiler could place a constant object (such as a global) in memory that was marked read-only. The presence of mutable hints that this should not be done.

Here are some valid reasons to declare and use mutable data:

  • Thread safety. Declaring a mutable boost::mutex is perfectly reasonable.
  • Statistics. Counting the number of calls to a function, given some or all of its arguments.
  • Memoization. Computing some expensive answer, and then storing it for future reference rather than recomputing it again.
Lloyd
  • 21,843
  • 2
  • 16
  • 7
  • 3
    Good answer, except for comment regarding mutable being a "hint". This makes it seem as if the mutable member sometimes won't be mutable if the compiler placed the object into ROM. The behaviour of mutable is well defined. – Richard Corden Sep 22 '08 at 08:17
  • 2
    Apart from placing a const object in read-only memory, the compiler may also decide to optimize const fucntion calls out of a loop, for example. A mutable statistics counter in an otherwise const function will still allow such optimization (and count only one call) instead of preventing optimization just for the sake of counting more calls. – Hagen von Eitzen Aug 19 '14 at 12:31
  • 1
    @HagenvonEitzen - I'm pretty sure that is incorrect. A compiler cannot hoist functions out of a loop unless it can prove there are no side effects. That proof generally involves actually inspecting the implementation of the function (often after it is inlined) and not relying on `const` (and such an inspection will succeed or fail irrespective of `const` or `mutable`). Simply declaring the function `const` isn't enough: a `const` function is free to have side effects such as modifying a global variable or something passed to the function, so it isn't a useful guarantee for that proof. – BeeOnRope Jun 18 '17 at 22:28
  • 1
    Now, some compilers have special extensions such as gcc's __attribute__((const)) and __attribute__((pure)), which _do_ [have such effects](https://stackoverflow.com/questions/29117836/attribute-const-vs-attribute-pure-in-gnu-c), but that's only tangentially related to the `const` keyword in C++. – BeeOnRope Jun 18 '17 at 22:32
8

Well, yeah, that's what it does. I use it for members that are modified by methods that do not logically change the state of a class - for instance, to speed up lookups by implementing a cache:

class CIniWrapper
{
public:
   CIniWrapper(LPCTSTR szIniFile);

   // non-const: logically modifies the state of the object
   void SetValue(LPCTSTR szName, LPCTSTR szValue);

   // const: does not logically change the object
   LPCTSTR GetValue(LPCTSTR szName, LPCTSTR szDefaultValue) const;

   // ...

private:
   // cache, avoids going to disk when a named value is retrieved multiple times
   // does not logically change the public interface, so declared mutable
   // so that it can be used by the const GetValue() method
   mutable std::map<string, string> m_mapNameToValue;
};

Now, you must use this with care - concurrency issues are a big concern, as a caller might assume that they are thread safe if only using const methods. And of course, modifying mutable data shouldn't change the behavior of the object in any significant fashion, something that could be violated by the example i gave if, for instance, it was expected that changes written to disk would be immediately visible to the app.

Shog9
  • 146,212
  • 34
  • 221
  • 231
7

Mutable is used when you have a variable inside the class that is only used within that class to signal things like for example a mutex or a lock. This variable does not change the behaviour of the class, but is necessary in order to implement thread safety of the class itself. Thus if without "mutable", you would not be able to have "const" functions because this variable will need to be changed in all functions that are available to the outside world. Therefore, mutable was introduced in order to make a member variable writable even by a const function.

The mutable specified informs both the compiler and the reader that it is safe and expected that a member variable may be modified within a const member function.

mkschreder
  • 267
  • 1
  • 7
  • 14
5

mutable is mainly used on an implementation detail of the class. The user of the class doesn't need to know about it, therefore method's he thinks "should" be const can be. Your example of having a mutex be mutable is a good canonical example.

Greg Rogers
  • 33,366
  • 15
  • 63
  • 93
5

Your use of it isn't a hack, though like many things in C++, mutable can be hack for a lazy programmer who doesn't want to go all the way back and mark something that shouldn't be const as non-const.

JohnMcG
  • 8,283
  • 5
  • 36
  • 49
4

Use "mutable" when for things that are LOGICALLY stateless to the user (and thus should have "const" getters in the public class' APIs) but are NOT stateless in the underlying IMPLEMENTATION (the code in your .cpp).

The cases I use it most frequently are lazy initialization of state-less "plain old data" members. Namely, it is ideal in the narrow cases when such members are expensive to either build (processor) or carry around (memory) and many users of the object will never ask for them. In that situation you want lazy construction on the back end for performance, since 90% of the objects built will never need to build them at all, yet you still need to present the correct stateless API for public consumption.

Zack Yezek
  • 1,234
  • 14
  • 5
2

Mutable changes the meaning of const from bitwise const to logical const for the class.

This means that classes with mutable members are longer be bitwise const and will no longer appear in read-only sections of the executable.

Furthermore, it modifies type-checking by allowing const member functions to change mutable members without using const_cast.

class Logical {
    mutable int var;

public:
    Logical(): var(0) {}
    void set(int x) const { var = x; }
};

class Bitwise {
    int var;

public:
    Bitwise(): var(0) {}
    void set(int x) const {
        const_cast<Bitwise*>(this)->var = x;
    }
};

const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.

int main(void)
{
    logical.set(5); // Well defined.
    bitwise.set(5); // Undefined.
}

See the other answers for more details but I wanted to highlight that it isn't merely for type-saftey and that it affects the compiled result.

Kevin Cox
  • 2,709
  • 1
  • 26
  • 30
1

In some cases (like poorly designed iterators), the class needs to keep a count or some other incidental value, that doesn't really affect the major "state" of the class. This is most often where I see mutable used. Without mutable, you'd be forced to sacrifice the entire const-ness of your design.

It feels like a hack most of the time to me as well. Useful in a very very few situations.

Joe Schneider
  • 8,845
  • 7
  • 37
  • 57
1

The mutable can be handy when you are overriding a const virtual function and want to modify your child class member variable in that function. In most of the cases you would not want to alter the interface of the base class, so you have to use mutable member variable of your own.

Saurabh
  • 687
  • 5
  • 4
1

The mutable keyword is very useful when creating stubs for class test purposes. You can stub a const function and still be able to increase (mutable) counters or whatever test functionality you have added to your stub. This keeps the interface of the stubbed class intact.

Martin G
  • 14,280
  • 9
  • 69
  • 82
1

One of the best example where we use mutable is, in deep copy. in copy constructor we send const &obj as argument. So the new object created will be of constant type. If we want to change (mostly we won't change, in rare case we may change) the members in this newly created const object we need to declare it as mutable.

mutable storage class can be used only on non static non const data member of a class. Mutable data member of a class can be modified even if it's part of an object which is declared as const.

class Test
{
public:
    Test(): x(1), y(1) {};
    mutable int x;
    int y;
};

int main()
{
    const Test object;
    object.x = 123;
    //object.y = 123;
    /* 
    * The above line if uncommented, will create compilation error.
    */   

    cout<< "X:"<< object.x << ", Y:" << object.y;
    return 0;
}

Output:-
X:123, Y:1

In the above example, we are able to change the value of member variable x though it's part of an object which is declared as const. This is because the variable x is declared as mutable. But if you try to modify the value of member variable y, compiler will throw an error.

MikeMB
  • 17,569
  • 7
  • 51
  • 93
1

The classic example (as mentioned in other answers) and the only situation I have seen the mutable keyword used in so far, is for caching the result of a complicated Get method, where the cache is implemented as a data member of the class and not as a static variable in the method (for reasons of sharing between several functions or plain cleanliness).

In general, the alternatives to using the mutable keyword are usually a static variable in the method or the const_cast trick.

Another detailed explanation is in here.

Daniel Hershcovich
  • 3,311
  • 2
  • 26
  • 35
  • 1
    I've never heard of using static members as a general alternative to mutable members. And `const_cast` is only for when you _know_ (or have been guaranteed) that something will not be changed (e.g. when interfering with C libraries) or when you _know_ it wasn't declared const. I.e., modifying a const-casted const variable results in undefined behaviour. – Sebastian Mach Nov 19 '13 at 11:56
  • 1
    @phresnel By "static variables" I meant static automatic variables in the method (that stay across calls). And `const_cast` can be used to modify a class member in a `const` method, which is what I referred to... – Daniel Hershcovich Nov 21 '13 at 10:19
  • 1
    That was not clear to me, as you wrote "in general" :) With regards to modifying through `const_cast`, as said this is only allowed when the object was not declared `const`. E.g. `const Frob f; f.something();`, with `void something() const { const_cast(m_foo) = 2;` results in undefined behaviour. – Sebastian Mach Nov 21 '13 at 10:41
-2

The very keyword 'mutable' is actually a reserved keyword.often it is used to vary the value of constant variable.If you want to have multiple values of a constsnt,use the keyword mutable.

//Prototype 
class tag_name{
                :
                :
                mutable var_name;
                :
                :
               };   
lpapp
  • 47,035
  • 38
  • 95
  • 127