通过const_cast删除const并调用不修改结果对象的非const函数是否安全?

vso*_*tco 9 c++ const-cast

我知道const应该谨慎地进行抛弃- 并且任何const从初始const对象中删除-ness 然后修改对象的尝试都会导致未定义的行为.如果我们想删除const-ness以便我们可以调用一个不修改对象的非const函数,该怎么办?我知道我们应该实际标记这样的功能const,但是假设我使用的是一个没有const可用版本的"坏"代码.

那么,总结一下,下面的代码是"安全的"吗?我的猜测是,只要你没有最终修改对象你就可以了,但我不是百分百肯定.

#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?
}
Run Code Online (Sandbox Code Playgroud)

Che*_*Alf 7

相对于未定义的行为const_cast由C++ 11标准的§3.8/ 9定义(§3.8是"对象生存期"):

"在存储位置创建一个const具有静态,线程或自动存储持续时间的对象占用的新对象,或者在此类const对象在其生命周期结束之前占用的存储位置处导致未定义的行为.

§7.1.6.1/ 4(§7.1.6.1是" cv-qualifiers ")

"除了mutable可以修改声明的任何类成员(7.1.1)之外,任何const 在其生命周期内修改对象的尝试(3.8)都会导致未定义的行为.

换句话说,如果修改原始const对象,则获得UB ,否则返回1.

const_cast本身不引入UB.


§5.2.11/ 7中还有一个非规范性的注释,"根据类型",通过从a获得的指针或引用的写入const_cast,可能具有未定义的行为.

这个非规范性的说明是如此愚蠢,以至于它有自己的非规范性脚注,这解释说" const_cast并不仅限于转换掉一个const限定符的转换".

然而,仍然有了这个澄清,我没有想到任何情况下写入可以明确定义或不取决于类型,即,我没有理解这个说明.这里的另外两个答案集中在本说明中的"写"一词,并且必须通过§3.8/ 9进入UB-land,是的.对我来说相当可疑的方面是"取决于类型",这似乎是该注释的重要部分.


1)除非关于其他非const_cast相关事物的UB规则发挥作用,例如使以后在除typeid表达式之外的上下文中解除引用的指针归零.


CB *_*ley 6

这个特定的例子恰好是安全的(具有良好定义的行为),因为没有写入声明的对象const.


Bar*_*rry 6

我们在[dcl.type.cv]中有这个:

除了mutable可以修改声明的任何类成员(7.1.1)之外,任何const在其生命周期内修改对象的尝试(3.8)都会导致未定义的行为.

[expr.const.cast]中有一条注释(非规范性),其中说明:

[注:根据对象,一个类型的写操作通过指针,左值或指针数据成员从所得const_cast该擅自抛弃一个const修饰符可产生不确定的行为(7.1.6.1). - 尾注]

尝试在const_cast[可能]导致未定义的行为之后修改对象或写入操作.在这里,我们没有写操作.