const_cast作用:
作用:去除变量的const或volatile属性
说明,由于不了解volatile,这里不讲关于volatile的知识。
const_cast的用途:
用途:有时候需要把常量的值赋值给普通变量。
const char* max(const char* s1,const char* s2)
{
return strcmp(s1,s2) > 0 ? s1 : s2;
}
char* p = max("AAA","BBB");//错误
说明:由于防止函数max修改字符串s1 和 s2的内容,就在形参中加入const。在函数返回值时,由于指针p为非const指针,是不允许接受const值的。这就要求取出返回值的const限制,为p赋值。
const_cast的语法:
const_cast<type_id> (expression)
说明:
(1) type_id 和 expression的类型是一样的
(2) type_id 和 expression应该是引用或指针。
举例:
const int constNum = 0;
int& Num = const_cast<int&>(constNum);
int* pNum = const_cast<int*>(&constNum);
编译器处理方式:
先举个例子:
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const int constNum = 0;
int& Num = const_cast<int&>(constNum);
cout<<"两个变量的地址:"<<endl;
cout<<"&constNum = "<<&constNum<<endl;
cout<<"&Num = "<<&Num<<endl<<endl;
cout<<"原来的值:"<<endl;
cout<<"constNum = "<<constNum<<endl;
cout<<"Num = "<<Num<<endl<<endl;
Num = 10;
cout<<"现在的值:"<<endl;
cout<<"constNum = "<<constNum<<endl;
cout<<"Num = "<<Num<<endl;
system("pause");
}
输出:
问题:在执行 const_cast 转换后,发现 变量Num 的地址和constNum的地址是一样的,但对Num赋值后,也就是对这个地址赋值后,为什么输出的Num的值和constNum的值为什么不同,Num的值为新值,而ConstNum的值仍然是老值?
分析:这是属于常数折叠或者常量替换
(1)这是由于编译器一般不会为 const常量或者表达式分配内存空间的,而是在编译阶段求出常量表达式的值或者直接把常量的值放入一个符号表中,当const常量或常量表达式在程序中使用时,编译器会在编译阶段把该const常量替换为具体值,和C中的宏define类似。所以在执行cout<<constNum时,constNum的值一直从符号表中取出,而且在预编译后变成了cout<<10。
(2)如果我们在程序中取了这个const常量的地址,那么编译器将为此常量分配一个内存空间,生成一个常量副本, 此时所有通过地址对常量的操作都是针对该副本的。
所以,&constNum 的地址是一个编译器为其分配的临时空间,其中Num也指向这个临时空间,在执行 Num = 10 后,临时空间的值为10。
注意:
给出一个不需要使用 const_cast的例子:
const int constNum = 0;
int Num = constNum; //num = 0
这里,Num只是引用常量 constNum 中的值,除此之外,变量num和变量constNum 是两个没有半毛钱关系的变量。只有当使用引用或指针指向常量变量时才需要使用const_cast转换,因为在这两种情况才导致Num和常量constNum指向同一个空间,而可能修改constNum中的值。
总结一句,常量是不能改的,想改就找个副本给你改。