我们都知道const的作用是声明变量为常量,在程序中除非显示转换,否则无法修改声明为const的对象。
本文针对显示修改的情况,提醒了一种隐式的错误,以及解决办法。
考虑下面的代码:
#include<iostream> int main(){ const int a=0; int *p=const_cast<int*>(&a);//&a返回int *,const_cast<int*>显示转换为int*. *p =1; int b=*p; int c=a; std::cout<<“b: "<<b<<std::endl<<"c: "<<c<<std::endl; std::cout<<&a<<" "<<p<<std::endl; return 0; }
输出的结果是:
b: 1
c: 2
0x7fffe27cd63c 0x7fffe27cd63c
问题就在这里,我们通过*p改变了a的值,并且检查指针指向的地址和变量的地址一致。但是打印const对象的赋值,发现最终的值仍然没有改变。
如果这发生在了程序的某个角落,我们通过*p改变了a的值,但是在下一次用a的时候,得到的结果仍然没有改变,这将发生不可预测的问题。这再一次提醒了我们,不要轻易使用强制类型转换,这往往会导致一些我们难以察觉的错误。
解决这个问题很简单,利用volatile修饰符:让变量a每次访问都强制到内存中读取最新的数据。
#include<iostream> int main(){ const volatile int a=0; int *p=const_cast<int*>(&a);//&a返回int *,const_cast<int*>显示转换为int*. *p =1; int b=*p; int c=a; std::cout<<“b: "<<b<<std::endl<<"c: "<<c<<std::endl; return 0; }
输出结果是:
b: 1
c: 1
想来读者已经想到了原因:const修饰的对象,编译器进行了符号替换。下文中用到了const 对象,就进行替换,而不是从内存中提取最新的值。