是否会从“ this”中删除constness?然后更改成员值会调用未定义的行为? [英] Does casting away constness from "this" and then changing a member value invoke undefined behaviour?

查看:80
本文介绍了是否会从“ this”中删除constness?然后更改成员值会调用未定义的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在回应我对另一个问题的答案的评论时有人提出类似建议

In a response to my comment to some answer in another question somebody suggests that something like

void C::f() const
{
  const_cast<C *>( this )->m_x = 1;
}

由于定义了const对象,因此调用了未定义的行为。这是真的?如果不是,请引用允许这样做的C ++标准(请提及您引用的标准)。

invokes undefined behaviour since a const object is modified. Is this true? If it isn't, please quote the C++ standard (please mention which standard you quote from) which permits this.

对于它的价值,我一直使用它避免使成员变量 mutable 只需一种或两种方法(因为使用 mutable 的方法)它可以写入 all 方法)。

For what it's worth, I've always used this approach to avoid making a member variable mutable if just one or two methods need to write to it (since using mutable makes it writeable to all methods).

推荐答案

(尝试)修改a const对象(在C ++ 11中为7.1.6.1/4)。

It is undefined behavior to (attempt to) modify a const object (7.1.6.1/4 in C++11).

所以重要的问题是,什么是const对象,并且是 m_x 一个?如果是,则您有UB。如果不是,那么这里没有任何内容表明它将是UB -当然,出于某些未在此处指出的其他原因(例如,数据竞赛),它可能是UB。

So the important question is, what is a const object, and is m_x one? If it is, then you have UB. If it is not, then there's nothing here to indicate that it would be UB -- of course it might be UB for some other reason not indicated here (for example, a data race).

如果在类 C 的const实例上调用函数 f ,则 m_x 是const对象,因此行为未定义(7.1.6.1/5):

If the function f is called on a const instance of the class C, then m_x is a const object, and hence behavior is undefined (7.1.6.1/5):

const C c;
c.f(); // UB

如果函数 f 为在类 C 的非常量实例上调用,则 m_x 不是const对象,因此行为是据我们所知定义:

If the function f is called on a non-const instance of the class C, then m_x is not a const object, and hence behavior is defined as far as we know:

C c;
const C *ptr = &c;
c->f(); // OK

因此,如果您编写此函数,那么您将受到用户的摆布创建 C 的const实例并在其上调用该函数。也许 C 的实例仅由某个工厂创建,在这种情况下,您可以防止这种情况。

So, if you write this function then you are at the mercy of your user not to create a const instance of C and call the function on it. Perhaps instances of C are created only by some factory, in which case you would be able to prevent that.

如果您希望数据成员即使完整对象是 const 也可修改,则应将其标记为可变。这就是 mutable 的目的,即使在<$的const实例上调用 f ,它也会为您提供定义的行为c $ c> C 。

If you want a data member to be modifiable even if the complete object is const, then you should mark it mutable. That's what mutable is for, and it gives you defined behavior even if f is called on a const instance of C.

从C ++ 11开始, const 位成员可变数据成员上的函数和操作应该是线程安全的。否则,当您的类型与标准库函数和容器一起使用时,您将违反标准库提供的保证。

As of C++11, const member functions and operations on mutable data members should be thread-safe. Otherwise you violate guarantees provided by standard library, when your type is used with standard library functions and containers.

因此在C ++ 11中,您需要使 m_x 原子类型,或者以其他方式同步修改,或者作为最后一个文档,即使将其标记为const,函数 f 不是线程安全的。如果您不做任何事情,那么您会再次为用户创造一个机会,使他们可以编写他们认为合理的代码,但实际上具有UB。

So in C++11 you would need to either make m_x an atomic type, or else synchronize the modification some other way, or as a last resort document that even though it is marked const, the function f is not thread-safe. If you don't do any of those things, then again you create an opportunity for a user to write code that they reasonably believe ought to work but that actually has UB.

这篇关于是否会从“ this”中删除constness?然后更改成员值会调用未定义的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆