是否会从“ this”中删除constness?然后更改成员值会调用未定义的行为? [英] Does casting away constness from "this" and then changing a member value invoke undefined behaviour?
问题描述
在回应我对另一个问题的答案的评论时有人提出类似建议
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屋!