事出有因,附上代码:
#include<iostream>
int main(){
//volatile const int i=10;
const int i=10;
int *j=const_cast<int*>(&i);
*j=2;
std::cout<<&i<<" "<<j<<std::endl;
std::cout<<i<<" "<<*j<<std::endl;
return 0;
}
输出结果:
0x6afef8 0x6afef8
10 2
#include<iostream>
int main(){
volatile const int i=10;
//const int i=10;
int *j=const_cast<int*>(&i);
*j=2;
std::cout<<&i<<" "<<j<<std::endl;
std::cout<<i<<" "<<*j<<std::endl;
return 0;
}
结果
1 0x6afef8
2 2
通常我们理解通过const修饰的变量为常量,常量的值初始化后不再发生改变,且初始化发生在声明阶段。类中的常量成员初始化一般通过构造函数的初始化表列实现。同样的,我们知道局部变量都存储在内存的栈结构中,每一个变量又可以通过指针进行访问,那问题来了,如果我们获取到const 常量的内存地址,并通过指针修改这个内存地址处的值,能修改成功么?如果修改成果那const常量的值会发生变化么?
上述两段代码就是实验的结果。首先分析第一段代码发现我们可以获取到const修饰的变量i的内存地址并成功修改,既然修改成功了,并且我们知道两个变量的内存地址一样,正常情况下i和*j的值应该一样才对,为什么两者的值不一样呢?这就是const关键字的作用所在了,用const修饰的变量值并不是放在变量对应的内存中,而是存放在编译器的符号表中,需要计算的时候直接从符号表中取值,省去了访问内存的时间,所以即便内存中存储的值改变了,const修饰的变量值也不会改变。
如何让const修饰的变量的值跟着内存操作而发生改变呢?既然值存在符号表中,进行了优化,我们就让它不存在符号表中,不进行优化。如何不让编译器优化呢,这时候就是volatile彰显身手的时候了,volatile意为“易变的”,及可能在编译器的管辖范围之外由于某些情况值发生变动(计时器、中断等 ),所以不允许编译器对volatile修饰的变量进行优化,通过第二段代码我们也证实了我们的想法,但是为什么两者的地址不一样呢?难道是机器的原因(使用win10环境,编译器是GCC)?!!!waiting god 。。。