搜尋

首頁  >  問答  >  主體

c++如果我有一个成员变量仅在某个成员函数foo()调用的时候赋值,就不能声明foo()成const?

ringa_leeringa_lee2804 天前476

全部回覆(4)我來回復

  • 巴扎黑

    巴扎黑2017-04-17 13:32:41

    mutable啊,忘了?

    mutable list<int> _li;
    

    解決

    回覆
    0
  • 巴扎黑

    巴扎黑2017-04-17 13:32:41

    那你只有再套一層封裝了,你現在的要求就是在封裝的過程中使用封裝後的結果
    畢竟,要看你到底不希望哪部分程式碼對那個變數賦值,先分清楚哪一部分是使用者程式碼,再來討論存取權的問題。

    回覆
    0
  • PHPz

    PHPz2017-04-17 13:32:41

    如果我有一個成員變數只在某個成員函數foo()呼叫的時候賦值,就不能宣告foo()成const?

    如果你所說的「賦值」是指初始化的話(賦初值),一個類別的資料成員是不可能不被初始化的。如果這個資料成員沒有在建構函式的初始化列表裡進行初始化,那麼編譯器會對其進行預設初始化(default initialize)。所以不可能只在某個成員函數內才初始化該類別的資料成員。

    如果你所說的「賦值」不是指初始化,而是指改變現有值,那麼可以透過在資料成員宣告中加入mutable來做到。

    但是,使用mutable的時候要注意:

    • 在改變聲明中包含mutable的資料成員的時,不應該影響這個類別的外在狀態。

    換句話說:

    • 聲明中包含mutable的資料成員應該用來描述類別內部的狀態,這些資料成員的改變不會從邏輯上改變這個類別的狀態。

    例如用於程式偵錯的成員、用於快取(或說被延遲賦值)的成員、用於存取偵測的成員、用於互斥鎖的成員等可以使用mutable,因為這些成員的改變並沒有在邏輯上改變對應類別的狀態。

    舉幾個例子:

    class C {
    private:
      mutable size_t visit_foo_count = 0;  // 程序调试
    public:
      void foo() const {
        // do something
        ++visit_foo_count;
      }
    };
    
    int main() {
      const C c;
      c.foo();
    }

    上面這個例子中,改變visit_foo_count並沒有從邏輯上改變類別C的狀態,從使用者的角度看,每次調用c.foo()的時候其效果都相同。

    class MathObject {
    private:
      mutable bool pi_cached;  // 访问检测
      mutable double pi_val;  // 缓存结果,延迟赋值
    public:
      MathObject() : pi_cached(false) { }  // pi_val 默认初始化,为随机值
      double pi() const {
        if(!pi_cached) {
          // 这个操作开销很高,而结果是重复的,所以可以缓存起来
          pi_val = 4;
          for(long step = 3; step < 1000000000; step += 4)
            pi_val += ((-4.0/(double)step) + (4.0/((double)step+2)));
          pi_cached = true;
        }
        return pi_val;
      }
    };
    
    int main() {
      const MathObject mo;
      mo.pi();
    }

    這個例子同理,從使用者的角度看,每次呼叫mo.pi()的時候結果都一樣,使用者並不知道只有在第一次呼叫時候才會進行pi_val的計算,也不知道如果一次都不呼叫就不會計算pi_val

    引申

    • C++11 標準

    C++11 Standard § 7.1.2/11 The mutable specifier on a class data member nullifies a const specifier applied to the containing class object and. mutable class member even though the rest of the object is const.

    • 關於 mutable 的一篇部落格:C++'s mutable and conceptual constness

    • Stack Overflow 的討論:Purpose of the mutable keyword

    回覆
    0
  • 高洛峰

    高洛峰2017-04-17 13:32:41

    gcc可以使用-fpermissive選項關掉這個錯誤,然後這個錯誤就是警告了,如果你是別的編譯器肯定有相應的選項,我也認為mutable是一個很好的解決方案。

    回覆
    0
  • 取消回覆