【问题标题】:C++ mutable specifierC++ 可变说明符
【发布时间】:2014-06-17 15:36:38
【问题描述】:

什么时候可以,什么时候不能调用可变变量?

int/float/bool 值很清楚。 但是,比方说,数组。如果我要向它添加元素,我可以调用原生数组mutable 吗?与std::vector 相同。

还有一个例子。我有对象 A,它保持对另一个对象 B 的引用 (B &b)。对象 B 有本机数组,我将重新分配/std::vector(我认为在这种特殊情况下是相似的)。伪代码:

struct B{
   std::vector<int> arr;
   // int *arr;              //Or this
   void changeArr(){
     arr.push_back(90);
   }
}

struct A{
   A(B &b) : b(b){};
   mutable B &b;     // is it ok to have it "mutable"?
   //mutable B b;    // or even this?
   void fire() const{
      b.arr.push_back(125);
      // Or 
      b.changeArr();
   }
}

我可以打电话给B &amp;b mutable 吗?


更新

根据http://en.cppreference.com/w/cpp/language/cv

mutable - 定义一个类的成员不影响 类的外部可见状态。

这是什么externally visible state of the class?当我增加数组大小,重新分配一些东西时,我会改变它吗?如果没有,什么时候改变?

【问题讨论】:

  • mutable 类似于 constvolatile
  • 只有不是conststatic的成员变量才可能是mutable
  • 好的。但与const不同,en.cppreference.com/w/cpp/language/cv“可变——定义类的成员不影响类的外部可见状态。”它应该“不影响类的外部可见状态”。这个“类的外部可见状态”是什么?
  • mutable 关键字的一个示例是类中的可变互斥锁,可以锁定在const 函数中。互斥量不能为const,因为需要修改,但需要在const函数中修改,所以需要mutable限定符。

标签: c++ mutable


【解决方案1】:

让我们举两个经典的例子来说明 mutable 的用处:

1。记住计算 (memoization)

class prime_caclulator {
    private:
        mutable std::vector<int> m_primes;

    public:
        get(int n) const {
            // 1. If the nth prime is in m_primes, return it.
            // 2. Otherwise, calculate the nth prime.
            // 3. Store the nth prime in m_primes.
            // 4. Return that prime.
        }
};

这里,我们有一个常量函数get(),它不需要改变这个对象的内部状态来计算第n个素数。但是,跟踪先前计算的素数可能会有所帮助,以提高该对象的性能。

这个内部状态,在这里我们称为m_primes,可能会在调用get() 时发生变化,因此我们需要将其标记为可变。请注意,该对象的不同内容只会改变调用所花费的时间,而不是它最终返回的内容。

2。线程安全

template <typename T>
class thread_safe_queue {
    private:
        mutable std::mutex m_mutex;
        std::queue<T> m_queue;

    public:
        size_t size() const {
            std::lock_guard<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        void push(T value) {
            std::lock_guard<std::mutex> lock(m_mutex);
            m_queue.push(value);
        }

        T pop() {
            std::lock_guard<std::mutex> lock(m_mutex);
            T top = m_queue.front();
            m_queue.pop();
            return top;
        }
};

在这种情况下,如果我们没有可变互斥体,那么我们将无法让 size() 成为 const,因为我们在该函数的过程中修改了 m_mutex

【讨论】:

  • mutable 的第三个经典且合理的用例是引用计数:如果您有一个保留自己的引用计数的类,您希望引用计数为 mutable。添加对对象的引用不会改变其逻辑状态,应该可以通过const 指针保留对象。
  • 所以,如果我对第 1 点的理解正确的话。可以(通过设计)拥有可变变量,它同时具有 setter(非 const)和 getter(const)。只是为了澄清。 coliru.stacked-crooked.com/a/0cc6b5f7a3b63dd6
  • @tower120:老实说,我不确定该示例是否格式正确。对于其他读者,请注意该对象是由非常量引用返回的。
  • 因为我的回答被抨击和删除了......示例一无效。根据 c++ 之神channel9.msdn.com/posts/… mutable 表示按位 const 或内部同步。我们的第一个示例将打破该规则,因为您没有提及同步。第二个示例使用默认同步的互斥锁。 ...而且我认为该链接在不久的将来不会过时。
  • @sharth 如果我将 const 引用添加到 get 的返回值? coliru.stacked-crooked.com/a/0dd9171437de667b
猜你喜欢
  • 1970-01-01
  • 2013-10-09
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2012-03-14
  • 2011-02-06
相关资源
最近更新 更多