2013-07-24 112 views
3

我知道修改声明为常量的对象是UB。标题中提到的更复杂的例子呢?修改const对象的非const成员

class Foo 
{ 
    public: 
     Foo (void) { } 
     int data; 
}; 

int main (void) 
{ 
    const Foo foo; 
    const_cast<Foo&>(foo).data = 0; // UB? 
    return 0; 
} 

data被声明为非常量因此可以修改它。但foo被声明为const。所以我们似乎无法修改它。因此我相信UB在这里被调用。我对吗?

更新:所以它出来,它实际上是一个UB。这意味着所有具有修改可变成员的假常量成员的类在常量实例上产生UB。

class Foo 
{ 
    public: 
     mutable int data; 
     Foo (void) { } 
     void foo (void) const 
     { 
      some_modifications_of_data(); 
     } 
}; 


const Foo foo; 
foo.foo(); // UB? 

这是否意味着,如果你设计这样的类必须明确提到,在任何情况下,没有人可以调用此方法在恒定的实例?

+1

不,对象是const,所以你不能修改它。 – chris

+1

是的,它是由标准的,未定义的。它可能在你的特定编译器中“工作”(因为在你设定的数据中为零),因为该选项是“未定义行为”的可能结果之一。 –

+0

@chris:'const_cast'确实摆脱了'const',所以编译器会编译这个,生成一些代码,可能实际上可能“不工作”。 –

回答

5

使用const_cast修改const数据结构中的数据确实是未定义的行为。例外是标记为mutable的项目。这些值的重点在于,即使对象的其余部分为const,它们也是可以修改的。这真的意味着“但这不是const”。

由于几乎所有的const都是关于编译器检测修改的,尽管在技术上允许编译器将一些const变量放在“不可写内存”中。关键字mutable允许“绕过”常量,所以编译器不会将const对象放入不可写入的内存中,如果该对象具有可变组件,当然,它不会“对象”到const对象在其可变组件中被修改 - 即使在const函数中。

+0

谢谢你的解释。 – Kolyunya