C++中四种范例转换 const_cast是否能改变常量
副标题#e#
we have four specific castingoperators:dynamic_cast, reinterpret_cast, static_cast and const_cast. Their format is to follow the new type enclosed between angle-brackets (<>) and immediately after, the expression to be converted between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
一、对C++中四种范例转换总结如下:
const_cast(expr)
用来移除工具的常量性(cast away the constness)
const_cast一般用于指针可能引用
利用const_cast去除const限定的目标不是为了修改它的内容
利用const_cast去除const限定,凡是是为了函数可以或许接管这个实际参数
static_cast(expr)
编译器隐式执行的任何范例转换都可以由static_cast完成
当一个较大的算术范例赋值给较小的范例时,可以用static_cast举办强制转换。
可以将void*指针转换为某一范例的指针
可以将基类指针转换为派生类指针
无法将const转化为nonconst,这个只有const_cast才可以办获得
reinterpret_cast(expr)
“凡是为操纵数的位模式提供较低层的从头表明”也就是说将数据以二进制存在形式的从头表明。
int i;
char *p = "This is a example.";
i = reinterpret_cast<int>(p);
//此时功效,i与p的值是完全沟通的。
int *ip
char *pc = reinterpret_cast<char*>(ip);
// 措施员需要记得pc所指向的真实工具是int型,并非字符串。
// 假如将pc看成字符指针举办操纵,大概会造成运行时错误
// 如int len = strlen(pc);
dynamic_cast(expr)
执行“安详向下”转型操纵,也就是说支持运行时识别指针或所指向的工具,这是独一个无法用旧式语来举办的转型操纵。
dynamic_cast可谓是最严格的转换,static_cast次之,而reinterpret_cast则是最宽松的。假如你碰着不能将整型转变为函数指针的问题,你可以这样办理:
reinterpret_cast<LPFUN&>(nAddress);
留意LPFUN这里有个“&”标记,暗示引用,C++的引用其实就是用指针实现的,而这些“转换”其实都是指针的转换,所以加上引用标记编译才气通过。
#p#副标题#e#
二、也许各人都有过这样的迷惑:const_cast可以去除一个常量的const属性,去除const属性后应该可以对“常量”举办修改,通过调试器发明内存中的值是被改变的,但是再通报这个“常量”的时候,值却一直保持原状,实在离奇,在Windows下用VC、实验如此,在Linux下用g++实验也如此,我原先觉得和编译器的优化选项有干系,把所有优化选项封锁,照样没用,为什么?
写了个措施举办测试:
#include <iostream> using namespace std; void Fun(int &value) { cout << "Fun(val) = " << value << endl; } int main(void) { const int val = 100; int *ptr = const_cast<int *>(&val); *ptr = 200; cout << &val << endl; cout << ptr << endl; cout << "val = " << val << endl; cout << "*ptr = " << *ptr << endl; int &ref = const_cast<int &>(val); ref = 300; cout << "val = " << val << endl; cout << "ref = " << ref << endl; Fun(const_cast<int &>(val)); return 0; }
输出为:
可以看出打印的地点是一样的,并且奇怪的是val照旧便是100,而通过*ptr打印出来的却是变动后的200,再者Fun函数打印的是300,即被引用再次修改了一次,在打印语句四周配置断点并调试反汇编,截取一段如下图:
可以明明地看出系统是对val这个const举办了预处理惩罚般的替换,将它替换成“64h”(十六进制的64就是十进制的100),即在编译生成的指令中val就已经被替换成100了,其实加const只是汇报编译器不能修改而不是真正地不行修改,假如措施员不留意而去修改了它会报错,此刻我们操作const_cast去除了常量性,然后通过指针和引用对其举办了修改,所以通过指针打印可能引用传参的时候就能看出其内存确实变革了,但为了掩护val这个变量原来的const特性,所以每次我们利用val时,系统都将其替换成初始值100,确保了val照旧“不行变”的。记着,只有当const限定符加在已经初始化的全局变量前面的时候,此时变量处在.rodata段(linux下),才是真正的不行修改,不然通过指针都是可以修改的,固然编译进程中会发生告诫。
在linux下测试也是同样的输出功效:
附录:
MSDN上关于四种cast的说明:
reinterpret_cast Operator
#p#分页标题#e#
The reinterpret_cast operator allows any pointer to be converted into any other pointer type. It also allows any integral type to be converted into any pointer type and vice versa. Misuse of the reinterpret_cast operator can easily be unsafe. Unless the desired conversion is inherently low-level, you should use one of the other cast operators.
dynamic_cast Operator
The expression dynamic_cast( expression ) converts the operand expression to an object of type type-id. The type-id must be a pointer or a reference to a previously defined class type or a“pointer to void”. The type of expression must be a pointer if type-id is a pointer, or an l-value if type-id is a reference.
static_cast Operator
The expression static_cast < type-id > ( expression ) converts expression to the type of type-id based solely on the types present in the expression. No run-time type check is made to ensure the safety of the conversion.
const_cast operator
The const_cast operator can be used to remove the const, volatile, and __unaligned attribute(s) from a class.