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

时间:2015-04-26 20:47:36

标签: c++ const-cast

我知道应该谨慎地抛弃const - 并且任何尝试从最初的const对象中移除const - 然后修改对象会导致未定义行为。如果我们想删除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?
}

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:6)

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

  

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

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

  

[注意:根据对象的类型,通过指针,左值或指针进行写入操作   从const_cast生成的数据成员转出 const-qualifier 可能会产生未定义   行为(7.1.6.1)。 -end note]

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

答案 2 :(得分:6)

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

  

在存储位置创建一个具有静态,线程或自动存储持续时间的const对象占用的新对象,或者在存储位置创建这样的{{1}用于在其生命周期结束之前占用的对象导致未定义的行为。

§7.1.6.1/ 4 (§7.1.6.1是“ cv-qualifiers ”)

  

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

换句话说,如果你修改了 最初的const 对象,否则你得到UB,否则 1

const本身不会引入UB。

§5.2.11/ 7 另外还有一个非规范性的说明,“根据类型”,通过从const_cast获得的指针或引用进行写入,可能有未定义的行为。

这个非规范性的说明是如此愚蠢,以至于它有自己的非规范性脚注,这解释说“const_cast并不仅限于抛弃const_cast - 限定符的转换。”。< / p>

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

1)除非关于其他非const相关事物的UB规则发挥作用,例如将以后在除const_cast - 表达式之外的上下文中取消引用的指针置零。