const_cast用于添加或者删除指针或者引用的const属性,但是对于删除const属性的功能有一些bug:
可以构造结构体或者类的非const指针或者引用给新变量,但是原变量的const属性不变化,新变量可以修改对应的内容;但是如果是一个基本类型的const变量,譬如cosnt char *,const int等等,不会修改其内容。
所以,还是应该遵从这样的原则:使用const_cast去除const限定的目的绝对不是为了修改它的内容(来自:http://www.cnblogs.com/ider/archive/2011/07/22/cpp_cast_operator_part2.html)其中有些观点很有概括性,譬如:C++对于指针的转换是任意的,它不会检查类型,任何指针之间都可以进行互相转换。int * 可以强制转换为float*,const int *可以强制转换为int *,int *可以转换为char *
以下转自:http://blog.csdn.net/lwbeyond/article/details/6213382
1. 常量指针被转化成非常量指针,转换后指针指向原来的变量(即转换后的指针地址不变)。
- class A
- {
- public:
- A()
- {
- m_iNum = 0;
- }
- public:
- int m_iNum;
- };
- void foo()
- {
- //1. 指针指向类
- const A *pca1 = new A;
- A *pa2 = const_cast<A*>(pca1); //常量对象转换为非常量对象
- pa2->m_iNum = 200; //fine
- //转换后指针指向原来的对象
- cout<< pca1->m_iNum <<pa2->m_iNum<<endl; //200 200
- //2. 指针指向基本类型
- const int ica = 100;
- int * ia = const_cast<int *>(&ica);
- *ia = 200;
- cout<< *ia <<ica<<endl; //200 100
- }
第一个工作正常,但后一个程序不能正常工作!!我继续尝试了不同的类型,比如char,short ,float,double等,发现了规律,凡是对结构体或类进行这个转换,都是成功的,但对char, short等基本类型的转换都没有成功。这是为什么呢?反汇编如下:
反汇编发现,虽然我没有使用优化,但系统还是对ica这个const进行了预编译般的替换,将它替换成“64h”(十六进制的64就是十进制的100)。其实ica地址上的值已经变了,这点从ia的输出可以看出,但由于系统对这个ica进行了预编译替换,从而导致输出ica的值没有变。这算是个C++的bug吧。
2. 常量引用被转换成非常量引用。
- class A
- {
- public:
- A()
- {
- m_iNum = 0;
- }
- public:
- int m_iNum;
- };
- void foo()
- {
- //1. 指针指向类
- const A *pca1 = new A;
- A *pa2 = const_cast<A*>(pca1); //常量对象转换为非常量对象
- pa2->m_iNum = 200; //fine
- //转换后指针指向原来的对象
- cout<< pca1->m_iNum <<pa2->m_iNum<<endl; //200 200
- //2. 指针指向基本类型
- const int ica = 100;
- int * ia = const_cast<int *>(&ica);
- *ia = 200;
- cout<< *ia <<ica<<endl; //200 100,本应该输入200 200的
- }
同样有上面那个问题,原因也是一样的。
3. 常量对象(或基本类型)不可以被转换成非常量对象(或基本类型)。
- void foo()
- {
- //常量对象被转换成非常量对象时出错
- const A ca;
- A a = const_cast<A>(ca); //不允许
- const int i = 100;
- int j = const_cast<int>(i); //不允许
- }
记住这种转换只是开了一个接口,并不是实质上的转换。(其实也算是实质上的转换了,只不过表达上不允许这样写)
4. 添加const属性
- int main(int argc, char ** argv_)
- {
- int i = 100;
- int *j = &i;
- const int *k = const_cast<const int*>(j);
- //const int *m = j; 感觉和这样写差不多
- //指的地址都一样
- cout <<i<<","<<&i<<endl; //100, 0012FF78
- cout <<*j<<","<<j<<endl; //100, 0012FF78
- cout <<*k<<","<<k<<endl; //100, 0012FF78
- *j = 200;
- //*k = 200; //error
- return 0;
- }
三. 总结:
1. 使用const_cast去掉const属性,其实并不是真的改变原类类型(或基本类型)的const属性,它只是又提供了一个接口(指针或引用),使你可以通过这个接口来改变类型的值。也许这也是const_case只能转换指针或引用的一个原因吧。
2. 使用const_case添加const属性,也是提供了一个接口,来不让修改其值,不过这个添加const的操作没有什么实际的用途(也许是我认识太浅了)。
3. 从对基本类型(int,char)的输出来看,使用const_case转换后的输出有点像闹剧!也许const_case只是给编译器用的。
4. 唉,使用const_case可能就是不让你用const_case?!