地球人都知道,在C/C++中,const关键字修饰变量时,该变量在初始化后就不允许被改变,如:
const int b;//C++17下出错,const变量初始化时就需要赋值。
const int b = 1;
b=2;//出错,const变量不允许通过这种方式改变。
然而,《Thinking in C++》第92页指出,可以通过对const变量的地址的强制类型转换实现改变const变量的值。
const int i = 0;
int *j = const_cast<int *)(&i); //也可以沿用C中的强制类型转换
*j = 1;
printf("%d %d",i,*j);
//结果是 0 1
奇怪的是,最后的结果通过i输出为原值0,通过指针解引用访问为修改值1,而且从debugger中看也是修改值1。
原来,由于编译器优化,编译器在遇见a时直接从寄存器读取初值,而不再从内存中读取,导致通过指针修改的a无法反应出来。也就是说,讲道理,const修饰的变量大多只能阻止程序员直接通过变量名修改,而无法封堵其他修改途径。
一个例外是,全局const变量无法通过指针方式修改其值,将会出现运行时错误。
const int a = 0;
int main(){
int* j= const_cast<int*>(&a);
*j =1; // 此行报运行时错误
printf("%d,%d",a,*j);
return 0;
}
在上面的第一行加上volatile修饰符,告诉编译器此变量“不知何时会改变”,相当于禁用编译器对此变量的优化。
volatile const int i = 0;
int *j = const_cast<int *)(&i); //也可以沿用C中的强制类型转换
*j = 1;
printf("%d %d",i,*j);
//结果是 1 1