通过 const_cast 删除 const 并调用不修改结果对象的非 const 函数是否安全?
Is it safe to remove const via const_cast and invoke a non-const function that does not modify the resulting object?
我知道丢弃 const
-ness 应该小心,任何尝试从最初的 const
对象中删除 const
-ness 然后修改对象结果在未定义的行为中。如果我们想删除 const
-ness 以便我们可以调用不修改对象的非常量函数怎么办?我知道我们实际上应该标记这样的函数 const
,但假设我使用的 "bad" 代码没有可用的 const
版本。
所以,总结一下,下面的代码是"safe"吗?我的猜测是,只要您最终不修改对象就可以了,但我不是 100% 确定。
#include <iostream>
struct Foo
{
void f() // doesn't modify the instance, although is not marked const
{
std::cout << "Foo::f()" << std::endl;
}
};
int main()
{
const Foo foo;
const_cast<Foo&>(foo).f(); // is this safe?
}
这个特定示例恰好是安全的(具有明确定义的行为),因为没有 write 到声明为 const
.
的对象
我们在 [dcl.type.cv] 中有这个:
Except that any class member declared mutable
(7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.
并且 [expr.const.cast] 中有一条注释(非规范)指出:
[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer
to data member resulting from a const_cast
that casts away a const-qualifier may produce undefined
behavior (7.1.6.1). —end note ]
在 const_cast
之后尝试修改对象或写操作 [可能] 会导致未定义的行为。在这里,我们没有写操作。
关于 const_cast
的未定义行为由 C++11 标准的 §3.8/9 定义(§3.8 是“对象生命周期”):
” Creating a new object at the storage location that a const
object with static, thread, or automatic storage duration occupies or, at the storage location that such a const
object used to occupy before its lifetime ended results in undefined behavior.
和§7.1.6.1/4(§7.1.6.1 是“cv-qualifiers”)
” Except that any class member declared mutable
(7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.
换句话说,如果你修改一个原来的const
对象,你会得到UB,否则1不是。
const_cast
本身不引入UB
在 §5.2.11/7 中还有一个非规范性说明“取决于类型”通过指针写入或从 const_cast
, 可能有未定义的行为。
这个非规范性的说明太冗长了,以至于它有自己的非规范性脚注,解释说“const_cast
不限于丢弃 const
-限定符的转换。” .
然而,尽管如此,我仍然没有想到写入可以根据类型明确定义或不明确定义的任何情况,即,我无法理解这个注释。这里的其他两个答案集中在本说明中的“写入”一词,这是通过 §3.8/9 进入 UB-land 所必需的,是的。对我来说相当可疑的方面是“取决于类型”,这似乎是该注释的重要部分。
1) 除了关于其他非 const_cast
相关事物的 UB 规则发挥作用,例如将稍后在 typeid
-expression.
以外的上下文中取消引用的指针置空
我知道丢弃 const
-ness 应该小心,任何尝试从最初的 const
对象中删除 const
-ness 然后修改对象结果在未定义的行为中。如果我们想删除 const
-ness 以便我们可以调用不修改对象的非常量函数怎么办?我知道我们实际上应该标记这样的函数 const
,但假设我使用的 "bad" 代码没有可用的 const
版本。
所以,总结一下,下面的代码是"safe"吗?我的猜测是,只要您最终不修改对象就可以了,但我不是 100% 确定。
#include <iostream>
struct Foo
{
void f() // doesn't modify the instance, although is not marked const
{
std::cout << "Foo::f()" << std::endl;
}
};
int main()
{
const Foo foo;
const_cast<Foo&>(foo).f(); // is this safe?
}
这个特定示例恰好是安全的(具有明确定义的行为),因为没有 write 到声明为 const
.
我们在 [dcl.type.cv] 中有这个:
Except that any class member declared
mutable
(7.1.1) can be modified, any attempt to modify aconst
object during its lifetime (3.8) results in undefined behavior.
并且 [expr.const.cast] 中有一条注释(非规范)指出:
[Note: Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a
const_cast
that casts away a const-qualifier may produce undefined behavior (7.1.6.1). —end note ]
在 const_cast
之后尝试修改对象或写操作 [可能] 会导致未定义的行为。在这里,我们没有写操作。
关于 const_cast
的未定义行为由 C++11 标准的 §3.8/9 定义(§3.8 是“对象生命周期”):
” Creating a new object at the storage location that a
const
object with static, thread, or automatic storage duration occupies or, at the storage location that such aconst
object used to occupy before its lifetime ended results in undefined behavior.
和§7.1.6.1/4(§7.1.6.1 是“cv-qualifiers”)
” Except that any class member declared
mutable
(7.1.1) can be modified, any attempt to modify aconst
object during its lifetime (3.8) results in undefined behavior.
换句话说,如果你修改一个原来的const
对象,你会得到UB,否则1不是。
const_cast
本身不引入UB
在 §5.2.11/7 中还有一个非规范性说明“取决于类型”通过指针写入或从 const_cast
, 可能有未定义的行为。
这个非规范性的说明太冗长了,以至于它有自己的非规范性脚注,解释说“const_cast
不限于丢弃 const
-限定符的转换。” .
然而,尽管如此,我仍然没有想到写入可以根据类型明确定义或不明确定义的任何情况,即,我无法理解这个注释。这里的其他两个答案集中在本说明中的“写入”一词,这是通过 §3.8/9 进入 UB-land 所必需的,是的。对我来说相当可疑的方面是“取决于类型”,这似乎是该注释的重要部分。
1) 除了关于其他非 const_cast
相关事物的 UB 规则发挥作用,例如将稍后在 typeid
-expression.