你什么时候使用C++'mutable'关键字?

30 c++

你什么时候使用C++ mutable关键字?为什么?我认为我不必使用该关键字.我知道它用于诸如缓存(或者可能是记忆)之类的东西,但是你需要在什么类和条件下使用它呢?

Joh*_*mew 46

有时,我使用它来将互斥或其他线程同步原语标记为可变,以便通常标记的访问器/查询方法const仍然可以锁定互斥锁.

当您需要检测代码以进行调试或测试时,它有时也很有用,因为检测通常需要从内部查询方法中修改辅助数据.

  • 我发现这是我一直在使用的代码中最常见的可变用途.事实上,在声明它们时我默认使用`mutable mutex`,而没有考虑语言是否需要`mutable`关键字.毕竟,`mutex`不是对象状态的一部分. (10认同)

小智 14

在内部成员计算的对象缓存结果的情况下,我使用了mutable:

class Transformation
{
    private:
        vec3 translation;
        vec3 scale;
        vec4 rotation;
        mutable mat4 transformation;
        mutable bool changed;
    public:
        Node()
        {
            [...]
            changed = false;
        }
        void set_translation(vec3 _translation)
        {
            translation = _translation;
            changed = true;
        }
        void set_scale(...) ...


        mat4 get_transformation() const
        {
            if(changed)
            {
                 // transformation and changed need to be mutable here
                 transformation = f(translation, scale, rotation); // This take a long time...
                 changed = false;
            }
            return transformation;
        }
};

void apply_tranformation(const Transformation* transfo)
{
    apply(transfo->get_transformation());
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*wis 10

Google代码搜索显示了许多用途.例如,在XTR加密的实现中,使用可变成员,以便方法可以返回对结果的引用(防止制作副本).

再举一个例子,Webkit使用它来懒惰地初始化成员数据(m_lineHeight).

  • 提供的链接已损坏 (4认同)

Tim*_*imW 5

在模拟对象中捕获成员变量中 const 函数的参数值。

class Source
{
public:
    virtual ~Source() {}
    virtual std::string read(int count) const=0;
};

class SourceMock : public Source
{
public:
    mutable std::vector<int> arguments;
    std::string read(int count) const {
        arguments.push_back(count);
        return "...";
    }
};

//TEST....
SourceMock mock;
//...
VERIFY(mock.arguments.size()==2);
VERIFY(mock.arguments[0]==3);
//...
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 5

我在锁定互斥体以确保线程安全时使用它。互斥体被标记为可变的,因此锁定它的方法可以保持常量。


Tho*_*ews 5

mutable用于按需初始化的类成员,特别是来自程序外部的数据库或源.这允许"getter"函数按需创建对象,否则它是一个常量方法.