为什么对一个const int指针使用const_cast,将他的值赋值给一个int,通过这个int指针改变常量的值时,编译器通过, 但是输出常量的时候仍然是原来的值,把int指针通过*解引用输出是改变之后的值
const 的机制,就是在编译期间,用一个常量代替了 data。这种方式叫做常量折叠。
常量折叠与编译器的工作原理有关,是编译器的一种编译优化。在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。
常量折叠只对原生类型起作用,对我们自定义的类型,是不会起作用的。
应用场景是去除只读属性,但有一个前提是内存本身必须是可以修改的。
#include <iostream>
using namespace std;
void MyPrintStr1(const char* str) //const char* str,对实参设置只读属性,防止误修改
{
cout << str << endl;
}
void MyPrintStr2(const char* str)
{
cout << str << endl;
//str[0] = 'H'; //需要修改实参的场景,但const只读属性,无法修改内存
char* temp = NULL;
temp = const_cast<char*>(str);
temp[0] = 'H';
cout << str << endl;
}
int main()
{
//1.在堆栈上分配内存
char str1[] = "how to use const_cast";
MyPrintStr2(str1);
//2.使用常量区字符串(内存的常量区不可修改)
const char* pStr = "how to use const_cast";
MyPrintStr1(pStr);
//MyPrintStr2(pStr);
//引发了异常: 写入访问权限冲突。temp 是 0xDD9BF4。
//3.const 类型的字符串
const char str2[] = "how to use const_cast";
MyPrintStr2(str2);
system("pause");
return 0;
}
在测试函数中,我们分了三种情况,可以看出第1、3种情况可以正常通过const_cast去除只读属性,从而达到修改内存数据的目的,而第2种情况却出现了异常。这是因为,第1、3种情况虽然对字符串增加了只读属性,但是内存本身是在栈上分配的,而栈内存本身是可以修改的,所以运行成功。而第二种情况是使用了常量区(全局区)的内存,这段内存是不可修改的,所以即使我们使用const_cast去除了字符串的只读属性,也无法正常运行,这是因为内存本身不可修改的原因。所以,在使用const_cast的时候,首先要知道,const属性的变量是在哪分配的内存,该内存本身是否可以修改。