const 函数中的成员赋值

发布于 2024-08-12 05:41:57 字数 375 浏览 5 评论 0原文

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

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

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

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

我可以分配我的成员而不需要使成员可变吗?如何?使成员可变是否有任何副作用?

I have a class member myMember that is a myType pointer. I want to assign this member in a function that is declared as const. I'm doing as follows:

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

Doing this works fine in VC++, but GCC gives an error with the message "lvalue required as left operand of assignment".

Making the member mutable allow me to simply remove the const_cast and assign the value. However, I'm not entirely sure that that comes with other side-effects.

Can I assign my member without having to make the member mutable? How? Are there any side-effects in making members mutable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

情话难免假 2024-08-19 05:41:57

这种情况——封装的内部状态更改不会影响外部状态(例如缓存结果)——正是 mutable 关键字的用途。

This scenario -- an encapsulated internal state change that does not impact external state (e.g. caching results) -- is exactly what the mutable keyword is for.

何止钟意 2024-08-19 05:41:57

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

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

或[来自其他响应,谢谢:P]:

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

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

正如您从围绕这个问题的激烈辩论中看到的,随意使用 mutable 和大量 const_cast 肯定是代码中出现不良气味的症状。从概念的角度来看,放弃常量或使用可变可能会产生更大的影响。在某些情况下,正确的做法可能是将方法更改为非常量,即承认它正在修改状态。

这一切都取决于 const 正确性在您的上下文中有多重要 - 您不想最终像仙尘一样散布 mutable 来让东西工作,但 mutable 是有意的如果该成员不是对象的可观察状态的一部分,则可以使用。最严格的 const 正确性观点认为,对象状态的任何一个位都不能被修改(例如,如果您的实例位于 ROM 中,这可能很关键......) - 在这些情况下,您不需要任何 constness丢失。在其他情况下,您可能会将一些外部状态存储在对象之外的某个位置 - 例如,在决定是否合适时也需要考虑特定于线程的缓存。

The code wont actually work in VC++ - you're not updating the value (or at least it shouldnt), hence the warning from GCC. Correct code is

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

or [from other response, thanks :P]:

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

Making it mutable effectively means you get implicit const_casts in const member functions, which is generally what you should be steering towards when you find yourself doing loads of const_casts on this. There are no 'side-effects to using mutable' other than that.

As you can see from the vehement debates circling this question, willy-nilly usage of mutable and lots of const_casts can definitely be symptoms of bad smells in your code. From a conceptual point of view, casting away constness or using mutable can have much larger implications. In some cases, the correct thing to do may be to change the method to non-const, i.e., own up to the fact that it is modifying state.

It all depends on how much const-correctness matters in your context - you dont want to end up just sprinking mutable around like pixie dust to make stuff work, but mutable is intended for usage if the member isnt part of the observable state of the object. The most stringent view of const-correctness would hold that not a single bit of the object's state can be modified (e.g., this might be critical if you're instance is in ROM...) - in those cases you dont want any constness to be lost. In other cases, you might have some external state stored somewhere ouside of the object - e.g., a thread-specific cache which also needs to be considered when deciding if it is appropriate.

带上头具痛哭 2024-08-19 05:41:57

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

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

请记住,mutable 并不是一种规避常量正确性的机制;而是一种机制。这是一个改进它的机制。

const_cast is nearly always a sign of design failure. In your example, either func() should not be const, or myMember should be mutable.

A caller of func() will expect her object not to change; but this means "not to change in a way she can notice"; this is, not to change its external state. If changing myMember does not change the object external state, that is what the mutable keyword is for; otherwise, func() should not be const, because you would be betraying your function guarantees.

Remember that mutable is not a mechanism to circunvent const-correctness; it is a mechanism to improve it.

私藏温柔 2024-08-19 05:41:57
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
class Class{
int value;
void func()const{
const_cast<Class*>(this)->value=123;
}
};
万劫不复 2024-08-19 05:41:57

正如 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;
  }

  ...   
}

因此,如果您将 IRestrictedReader * 而不是 const MyClass * 传递给某个函数,它可以调用 func 并因此改变 mValueToBeWrittenFromEverybodymOtherValue1 是一种“const”。

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

As Steve Gilham wrote, mutable is the correct (and short) answer to your question. I just want to give you a hint in a different direction.
Maybe it's possible in your szenario to make use of an (or more than one) interface?
Perhaps you can grok it from the following example:

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

  ...   
}

So, if you pass to some function an IRestrictedReader * instead of a const MyClass * it can call func and thus change mValueToBeWrittenFromEverybody whereas mOtherValue1 is kind of "const".

. I find mutable always a bit of a hack (but use it sometimes).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文