我希望有人能够澄清C++中未定义行为的确切含义。给定以下类定义:
class Foo
{
public:
explicit Foo(int Value): m_Int(Value) { }
void SetValue(int Value) { m_Int = Value; }
private:
Foo(const Foo& rhs);
const Foo& operator=(const Foo& rhs);
private:
int m_Int;
};
如果我理解正确,以下代码中的两个const_cast将会去除类型为Foo的原始对象的const属性,但是任何尝试通过指针或引用修改此对象的操作都将导致未定义的行为。
int main()
{
const Foo MyConstFoo(0);
Foo& rFoo = const_cast<Foo&>(MyConstFoo);
Foo* pFoo = const_cast<Foo*>(&MyConstFoo);
//MyConstFoo.SetValue(1); //Error as MyConstFoo is const
rFoo.SetValue(2); //Undefined behaviour
pFoo->SetValue(3); //Undefined behaviour
return 0;
}
令我感到困惑的是,为什么这似乎可行,并且将修改原始的const对象,但它甚至没有提示我警告来通知我这种行为是未定义的。我知道const_cast在广义上受到不赞成,但我可以想象一种情况,即没有意识到C样式转换可能会导致进行const_cast的情况,而这可能在不被注意的情况下发生,例如:
Foo& rAnotherFoo = (Foo&)MyConstFoo;
Foo* pAnotherFoo = (Foo*)&MyConstFoo;
rAnotherFoo->SetValue(4);
pAnotherFoo->SetValue(5);
在什么情况下,这种行为可能会导致致命的运行时错误?是否有一些编译器设置可以警告我这种(潜在的)危险行为?注:我使用MSVC2008。
const_cast
或C风格转换意味着,“我知道我正在做危险的事情,不要阻止我”。C++编译器和程序员的一般哲学是,在这里发出警告并没有用处,因为代码中存在const_cast
已经足够警告了。 - Steve JessopMyConstFoo
的引用传递到某些代码中,实际上不会修改它(并且已记录为不这样做等),但该代码并未考虑const安全性,因此需要使用Foo&
而不是const Foo&
。指针/引用的强制转换是危险的,并且用于危险的事情,因此需要额外的审查,这是避免使用它们的原因之一。尽管如此,有时候一些第三方库,特别是接受非const指针的旧C接口,会让您感到沮丧。 - Steve Jessop