不久前,我遇到了一些代码,它们用mutable关键字标记了一个类的成员变量。据我所知,它只是允许你在const方法中修改变量:

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

这是唯一的使用这个关键字还是有更多的它比满足眼睛?从那以后,我在一个类中使用了这种技术,将boost::mutex标记为mutable,允许const函数出于线程安全的原因锁定它,但是,说实话,这感觉有点hack。


当前回答

它允许区分按位的const和逻辑的const。逻辑const是指对象没有以通过公共接口可见的方式更改,就像锁定示例一样。另一个例子是一个类,它在第一次请求时计算一个值,并缓存结果。

因为c++11 mutable可以用在lambda上,表示用value捕获的东西是可修改的(默认情况下不是):

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

其他回答

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.

指定的可变变量通知编译器和读取器 成员变量可以在const中修改,这是安全和预期的吗 成员函数。

它在有隐藏内部状态(如缓存)的情况下非常有用。例如:

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;
};

然后可以让一个const HashTable对象仍然使用它的lookup()方法,该方法修改内部缓存。

当你重写一个const虚函数并想要修改该函数中的子类成员变量时,mutable可以很方便。在大多数情况下,您不希望更改基类的接口,因此必须使用自己的可变成员变量。

在某些情况下(比如设计糟糕的迭代器),类需要保留一个计数或其他一些附带的值,这并不真正影响类的主要“状态”。这是我最常看到使用mutable的地方。如果没有mutable,您将被迫牺牲设计的整个const-ness。

对我来说,大多数时候这也像个黑客。在非常非常少的情况下有用。

mutmutable确实存在,因为你可以推断允许在一个常量函数中修改数据。

这样做的目的是,您可能有一个函数对对象的内部状态“什么都不做”,因此您将函数标记为const,但您可能确实需要以不影响其正确功能的方式修改一些对象的状态。

关键字可以作为对编译器的提示——理论上的编译器可以将一个常量对象(例如全局变量)放在内存中,并将其标记为只读。可变的存在提示不应该这样做。

下面是声明和使用可变数据的一些有效理由:

线程安全。声明一个可变的boost::mutex是完全合理的。 统计数据。给定函数的部分或全部实参,计算函数的调用次数。 记忆。计算一些代价高昂的答案,然后将其存储起来以备将来参考,而不是重新计算。