const_cast是一种C++运算符,主要是用来去除复合类型中const和volatile属性(没有真正去除)。
我们需要注意的是:变量本身的const属性是不能去除的,要想修改变量的值,一般是去除指针(或引用)的const属性,再进行间接修改。
用法:const_cast<type>(expression)
通过const_cast运算符,也只能将const type*转换为type*,将const type&转换为type&。
也就是说源类型和目标类型除了const属性不同,其他地方完全相同。
我们先来看这样一段代码:
#include <iostream>
using namespace std;
int main () {
const int data = 100;
int *pp = (int *)&data;
*pp = 300;
cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
cout << " pp = " << *pp << "\t地址 : " << pp << endl << endl ;
int *p = const_cast<int*>( &data ) ;
cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
cout << " p = " << *p << "\t地址 : " << p << endl << endl ;
*p = 200 ;
cout << "data = " << data << "\t地址 : " << &data << endl << endl ;
cout << " p = " << *p << "\t地址 : " << p << endl << endl ;
return 0 ;
}
运行结果如下:
很奇怪? data 的地址是 0x6ffdfc, p 指向的地址也是 0x6ffdfc, 但是修改 p 之后, 同一个地址上的内容却不相同。
可能是 const 的问题? const 的机制,就是在编译期间,用一个常量代替了 data。这种方式叫做常量折叠。
常量折叠与编译器的工作原理有关,是编译器的一种编译优化。在编译器进行语法分析的时候,将常量表达式计算求值,并用求得的值来替换表达式,放入常量表。所以在上面的例子中,编译器在优化的过程中,会把碰到的data(为const常量)全部以内容100替换掉,跟宏的替换有点类似。
常量折叠只对原生类型起作用,对我们自定义的类型,是不会起作用的。
我们看下面的代码:
#include <iostream>
#include <stdio.h>
using namespace std;
typedef struct _Test {
int a;
_Test() {
a = 10;
};
void func {}
} Test;
int main()
{
const Test b;
Test *b1 = const_cast<Test *>(&b);
cout << "b = " << b.a << endl;
b1->a = 100;
cout << "b = " << b.a << ", *b1 = " << b1->a << endl;
return 0;
}
const_cast去除函数返回值的const属性。
函数的形参为非const,当我们传递一个const修饰的变量时可以通过const_cast去除该变量的const属性。
#include <iostream>
using namespace std;
const int *f(int *t)
{
int *p = new int;
*p = 100;
return p;
}
int main () {
int x = 1;
int *p1 = const_cast<int *>(f(&x));
*p1 = 1000;
const int *y = new int(10);
//int *p2 = const_cast<int *>(f(y));//[Note] in passing argument 1 of 'const int* f(int&)'
int *p2 = const_cast<int *>(f(const_cast<int *>(y)));
cout << *y <<endl;
// *y = 100; //[Error] assignment of read-only location '* y'
}