1、写在前面:
int main(void) { const int a = 0; int* ptr = const_cast<int*>(&a); *ptr = 10; int b = a; int c = b; cout << a << endl; cout << b << endl; cout << *(&a) << endl; cout << *ptr << endl; cout << (&a == ptr) << endl; }
对于以上代码,const声明了变量a为常量(伪常量),为什么叫伪常量呢?因为使用const_cast强制转换后,去掉其地址的const属性之后,使用ptr指针访问其地址并作修改,是合法的;真常量如p指向的内容为常量字符串,是不允许被修改的,但是同样的方法进行强制转换,编译不会报错,但是运行时,内核不会允许非法的写入操作,会抛出异常;
const char* p=“hello world”
2、分析const声明的常量的的实际优化过程:
对于这段代码,
1 int main(void) { 2 const int a = 0; 3 int* ptr = const_cast<int*>(&a); 4 5 *ptr = 10; 6 7 int b = a; 8 9 int c = b; 10 11 cout << a << endl; 12 cout << b << endl; 13 cout << *(&a) << endl; 14 cout << *ptr << endl; 15 cout << (&a == ptr) << endl; 16 17 }
先看运行结果:
这里可以看到,标识符a对应的内存的数据其实已经被ptr给改了,但是直接使用标志符a去赋值或者输出的时候,并没有以按地址取值的方式从内存空间去读相应的数据,因此我们可以猜想,必然是在某个环节作了替换操作。
2.1 看看这段代码预处理后的结果:并没有在预处理阶段作替换
2.2 再看看这段代码对应的汇编代码呢?:(虽然汇编没学过,但是对比来看可以看出区别)就是在编译阶段完成了替换,将标识符a直接替换成了一开始声明的数值,而不是去先读取对应的地址空间存放的值;
3、总结
从以上的分析过程可以看出,const声明的数据类型的优化是存在编译器中的,减少了一步取址操作,也就是说,只要你使用const声明了一个数据类型(这里只验证了内置数据类型),那么编译器就认定它不会被修改,因此在编译阶段就对它进行数值替换(因为实际上使用标识符a作为左值去对它进行重新赋值时,是不被允许的,编译时就会报错)。然而由于它的一开始声明时需要实际的内存空间去存放数据,但是块空间本质上又是可以读写的,只是因为const的属性在语法上作了限制而已,其实际地址空间是可以间接操作的,所以才被称为伪常量。
欢迎指正!转载请标明出处~ https://i.cnblogs.com/posts/edit;postId=15267210
原文:https://www.cnblogs.com/liwe1004/p/15267210.html