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

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

class A{
    list<int> _li; //我不希望在构造函数的时候进行赋值
public:
    A(){};
    void getLi(){  //这个函数如果不声明成const就不能被const变量调用,但由于修改成员变量不能被声明成const
        for (int i = 0; i < 10; i++) _li.push_back(i);
    }

};
void main(){
    const A a;
    a.getLi(); //编译报错
}

我应该怎么处理这种仅在调用某函数时赋值的情况?

我也想过用mutable,但我觉得mutable只适用于不描述对象属性的变量,用在这里是一种滥用,有没有别的解决方式?


那你只有再套一层封装了,你现在的要求就是在封装的过程中使用封装后的结果
毕竟,要看你到底不希望哪部分代码对那个变量赋值,先分清楚哪部分是用户代码,再来讨论访问权限的问题。


mutable啊,忘了?

mutable list<int> _li;

解决


gcc可以使用-fpermissive选项关掉这个错误,然后这个错误就是警告了,如果你是别的编译器肯定有相应的选项,我也认为mutable是一个很好的解决方案。


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

如果你所说的“赋值”是指初始化的话(赋初值),一个类的数据成员是不可能不被初始化的。如果这个数据成员没有在构造函数的初始化列表里进行初始化,那么编译器会对其进行默认初始化(default initialize)。所以不可能仅在某个成员函数内才初始化该类的数据成员。

如果你所说的“赋值”不是指初始化,而是指改变现有值,那么可以通过在数据成员声明中添加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 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.

【热门文章】
【热门文章】