9

我有一个类成员myMember,它是一个myType指针。我想在声明为 const 的函数中分配这个成员。我这样做如下:

void func() const
{
     ...
     const_cast<myType*>(myMember) = new myType();
     ...
}

这样做在 VC++ 中可以正常工作,但 GCC 会给出错误消息“需要左值作为赋值的左操作数”。

使成员可变允许我简单地删除 const_cast 并分配值。但是,我不完全确定这会带来其他副作用。

我可以在不使成员可变的情况下分配我的成员吗?如何?使成员可变有任何副作用吗?

4

5 回答 5

17

这个场景——一个不影响外部状态(例如缓存结果)的封装的内部状态变化——正是mutable关键字的用途。

于 2009-11-25T12:14:42.000 回答
8

该代码实际上不会在 VC++ 中工作 - 你没有更新值(或者至少它不应该),因此来自 GCC 的警告。正确的代码是

const_cast<myType*&>(myMember) = new myType();

或[来自其他回复,谢谢:P]:

const_cast<ThisType*>(this)->myMember = new myType();

有效地使其可变意味着您const_cast在成员函数中获得隐含的 s ,这通常是当您发现自己在执行大量s onconst时应该转向的方向。除此之外,没有“使用可变的副作用”。const_castthis

正如你从围绕这个问题的激烈辩论中看到的那样,随意使用mutable和很多const_casts 肯定是代码中异味的症状。从概念的角度来看,抛弃 constness 或使用mutable可能会产生更大的影响。在某些情况下,正确的做法可能是将方法更改为非常量,即承认它正在修改状态这一事实。

这完全取决于您的上下文中 const 正确性的重要性——您不希望最终只是mutable像精灵尘埃一样四处散布以使东西正常工作,但mutable如果成员不是对象的可观察状态的一部分,则打算使用它。最严格的 const 正确性观点认为,不能修改对象状态的任何一点(例如,如果您的实例在 ROM 中,这可能很关键......) - 在这些情况下,您不需要任何 constness丢失。在其他情况下,您可能会将一些外部状态存储在对象之外的某处 - 例如,在确定是否合适时也需要考虑特定于线程的缓存。

于 2009-11-25T12:15:51.457 回答
6

const_cast几乎总是设计失败的标志。在您的示例中,不func()应该是const,或者myMember应该是mutable

的调用者func()会期望她的对象不会改变;但这意味着“不要以她能注意到的方式改变”;这就是,不要改变它的外部状态。如果改变myMember不改变对象的外部状态,那就是mutable关键字的用途;否则,func()不应该const,因为你会背叛你的功能保证。

请记住,这mutable不是规避 const 正确性的机制;这是一种改进它的机制。

于 2009-11-25T12:27:09.937 回答
5
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
于 2009-11-25T12:14:45.760 回答
1

正如史蒂夫·吉尔汉姆(Steve Gilham)所写,mutable这是对您问题的正确(简短)答案。我只是想给你一个不同方向的提示。也许在您的场景中可以使用一个(或多个)界面?也许您可以从以下示例中了解它:

class IRestrictedWriter // may change only some members
{
public:
  virtual void func() = 0; 
}

class MyClass : virtual public IRestrictedWriter
{
public:
  virtual void func()
  {
    mValueToBeWrittenFromEverybody = 123; 
  }

  void otherFunctionNotAccessibleViaIRestrictedWriter()
  {
    mOtherValue1 = 123;
    mOtherValue2 = 345;
  }

  ...   
}

所以,如果你传递给某个函数 anIRestrictedReader *而不是 aconst MyClass *它可以调用func并因此改变mValueToBeWrittenFromEverybodymOtherValue1is 一种“const”。

. 我发现mutable总是有点 hack(但有时会使用它)。

于 2009-11-25T12:37:54.737 回答