我有以下代码:
const int k=1;
int *p=const_cast<int *>( &k);
cout<<"k before="<<*p<<endl;
*p=10;
*const_cast<int *>( &k)=12;
cout<<"k after="<<k<<endl;
输出是:
k before=1
k after=1
为什么const const不在这里工作?
答案 0 :(得分:12)
const_cast
会导致 undefined behaviour ,如果您丢弃const
然后写入该值。没有做任何事情都是有效的行为,正如你在这里看到的那样。
在您的特定示例中,可能发生的情况是编译器看到k
与const
存储类一起声明,知道它不能(合法地)更改并替换
cout<<"k after="<<k<<endl;
与
cout<<"k after="<<1<<endl;
如果您关闭优化,您可能(或可能不会)获得不同的结果。
抛弃const
调用未定义行为的原因是编译器可以自由地进行这样的优化。如果const
变量可以自由地转换为非const
变量并写入,那么const
对于编译器来说绝对没有意义。
答案 1 :(得分:4)
您正在做的是未定义的行为。您无法尝试修改const
答案 2 :(得分:2)
const_cast
的对象的const
指针时,通常会使用 const
。如果(在您的情况下)对象最初定义为const
,则尝试修改它会导致未定义的行为。没有const_cast
,编译器甚至不会让你尝试这样做(代码不会编译)。
然而,演员告诉编译器你确定你知道你在做什么并且它真的很安全,所以编译器只需要关闭并执行你告诉它的操作而不是给出任何错误/警告消息它通常可以做到。不幸的是,在这种情况下你正在做的是不真的很安全,但是既然你已经告诉编译器关闭并执行它,你将不会得到任何警告(至少与大多数编译器。)
关于你应该做什么,它归结为决定你的k
是否真的是常量。如果您确实需要修改它,则需要将其定义为普通(非const
)变量。如果你想确保只有少量的特定代码可以修改它,那么你可以/可以(对于一种可能性)将它私有化为一个小类:
class my_int {
int k;
public:
my_int() : k(1) {}
do_mod() { k = 10; }
operator int() { return k; }
};
现在,do_mod
可以直接修改k
。其他代码可以使用my_int
对象,就像它是int
一样,但不能修改它的值 - 实质上,它就像一个右值。
公平地说,我应该指出,如果真的尝试进行一些转换,其他代码可以修改k
的值。正如Bjarne所说,C ++的保护机制旨在预防事故,而非故意颠覆。