c++如果我有一个成员变量仅在某个成员函数foo()调用的时候赋值,就不能声明foo()成const?
ringa_lee
ringa_lee 2017-04-17 13:30:41
0
4
486
ringa_lee
ringa_lee

ringa_lee

reply all(4)
巴扎黑

mutable, forgot?

mutable list<int> _li;

Solution

巴扎黑

Then you only have to add another layer of encapsulation. Your current requirement is to use the encapsulated result during the encapsulation process.
After all, it depends on which part of the code you don’t want to assign a value to that variable. First, distinguish which part is the user code, and then discuss the issue of access permissions.

PHPzhong

If I have a member variable that is only assigned a value when a certain member function foo() is called, cannot I declare foo() as const?

If what you mean by "assignment" refers to initialization (assigning an initial value), it is impossible for the data members of a class not to be initialized. If this data member is not initialized in the constructor's initialization list, the compiler will perform default initialize. So it is not possible to initialize the data members of the class only within a certain member function.

If by "assignment" you don't mean initialization, but rather changing an existing value, you can do that by adding mutable to the data member declaration.

However, when using mutable, please note:

  • When changing the data member whose declaration contains mutable, it should not affect the external state of this class.

In other words:

  • Data members containing mutable in the declaration should be used to describe the internal state of the class. Changes to these data members will not logically change the state of the class.

For example, members used for program debugging, members used for caching (or delayed assignment), members used for access detection, members used for mutex locks, etc. can use mutable because of changes in these members It does not logically change the state of the corresponding class.

Give a few examples:

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

In the above example, changing visit_foo_count does not logically change the state of class C. From the user's perspective, the effect is the same every time c.foo() is called.

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

The same is true for this example. From the user's perspective, the result is the same every time mo.pi() is called. The user does not know that the calculation of pi_val will only be performed on the first call, nor does he know if pi_val will not be calculated without calling it once.

Extension

  • C++11 Standard

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 permits modification of the mutable class member even though the rest of the object is const.

  • A blog about mutable: C++'s mutable and conceptual constness

  • Stack Overflow discussion: Purpose of the mutable keyword

小葫芦

gcc can use the -fpermissive option to turn off this error, and then this error is a warning. If you are using another compiler, there must be corresponding options. I also think mutable is a good solution.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template