Does the 'mutable' keyword have any purpos

2019-01-01 01:42发布

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.

18条回答
唯独是你
2楼-- · 2019-01-01 02:01

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.

查看更多
姐姐魅力值爆表
3楼-- · 2019-01-01 02:02

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.
查看更多
十年一品温如言
4楼-- · 2019-01-01 02:05

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.

查看更多
萌妹纸的霸气范
5楼-- · 2019-01-01 02:07

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
查看更多
步步皆殇っ
6楼-- · 2019-01-01 02:09

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.

查看更多
余欢
7楼-- · 2019-01-01 02:10

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.

查看更多
登录 后发表回答