1. 一个经典实例

 /*
用法:const_cast<type_id> (expression)
  该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
  一、常量指针被转化成非常量指针,并且仍然指向原来的对象;
  二、常量引用被转换成非常量引用,并且仍然指向原来的对象;
  三、常量对象被转换成非常量对象。
type_id 必须为指针或引用
*/
class B
{
public:
int m_iNum;
B():m_iNum() {}
}; void foo()
{
const B *b1 = new B();
//b1->m_iNum = 100; //compile error
B *b2 = const_cast<B*>(b1);
b2->m_iNum = ;
cout<<"b1: "<< b1->m_iNum <<endl;
cout<<"b2: "<< b2->m_iNum <<endl;
cout<<endl;
const B b3;
//b3.m_iNum = 100; //compile error
B b4 = const_cast<B&>(b3);//b4 is another object
b4.m_iNum = ;
cout<<"b3: "<<b3.m_iNum <<endl;
cout<<"b4: "<<b4.m_iNum <<endl;
cout<<endl;
const B b5;
//b5.m_iNum = 100; //compile error
B &b6 = const_cast<B&>(b5);
b6.m_iNum = ;
cout<<"b5: "<<b5.m_iNum <<endl;
cout<<"b6: "<<b6.m_iNum <<endl;
cout << endl;
39 // force to convert
40 const int x = 50;
41 int* y = (int *)(&x);// same address, but the content is different
42 *y = 200;
43 cout << "x: "<<x<<" address: "<<&x<<endl;
44 cout << "*y: "<<*y<<" address: "<<y<<endl;
cout<<endl;
// int
47 const int xx = 50;
48 int* yy = const_cast<int *> (&xx);// same address, but the content is different
49 *yy = 200;
50 cout << "xx: "<<xx<<" address: "<<&xx<<endl;
51 cout << "*yy: "<<*yy<<" address: "<<yy<<endl;
52 cout<<endl;
// int
const int xxx = ;
int yyy = const_cast<int&> (xxx);// another int
yyy = ;
cout << "xxx: "<<xxx<<" address: "<<&xxx<<endl;
cout << "yyy: "<<yyy<<" address: "<<&yyy<<endl;
} int _tmain(int argc, char* argv[])
{
foo();
return ;
}

result:

b1: 200
b2: 200

b3: 50
b4: 200

b5: 200
b6: 200

x: 50 address: 002CF880
*y: 200 address: 002CF880

xx: 50 address: 002CF884
*yy: 200 address: 002CF884

xxx: 50 address: 002CF88C
yyy: 200 address: 002CF888

可以改变const 自定义类的成员变量,但是对于内置数据类型,却表现未定义行为。

2. 关于为啥会出现同一个地址,其值却不一样的情况

Program:
#include <iostream> using namespace std; int main()
{
const int a = 1;
int *p = const_cast<int*>(&a);
*p = 2;
cout << “value a=” << a << endl;
cout << “value *p=” << *p << endl;
cout << “address a=” << &a << endl;
cout << “address p=” << p << endl;
return 0;
}

  

这个程序,从语法上看,没有任何问题(当然,这种用法不提倡 deprecated )。但是输出结果却是这样的:

value a=1
value *p=2
address a=0xbfe9efb4
address p=0xbfe9efb4(depends on machine)

奇怪了,a和p既然指向同一块地址,为什么输出的内容却不一样呢?

在调试的时候发现,在运行完*p=2时,调试器打出的a的地址和p是一样的,而且a和*p的内容都是2。但为什么输出时候会a=1呢?

还是看汇编代码吧,相关部分:

subl $8, %esp
pushl $_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
subl $12, %esp
//将直接数1压栈
pushl $1
//栈顶指针减12
subl $12, %esp
pushl $.LC0
pushl $_ZSt4cout
.LCFI7:
//这句是”value a=”这个字符串的输出函数,char
call _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
//栈顶指针增加20
addl $20, %esp
pushl %eax
//这句是a的值输出,int
call _ZNSolsEi
addl $20, %esp
pushl %eax
.LCFI8:
//这句是输出的endl
call _ZNSolsEPFRSoS_E
addl $16, %esp

  

看完之后,有人会问了:怎么没看到a在哪里输出的啊,那么请你注意上面“栈顶指针增加20”这个注释,增加20之后它到哪里了?注意上面就会发现,前面有两次压栈,指针减4*2=8,一次指针减12,然后再加上20,这时候栈顶指针就到了“将直接数1压栈”下面了,显然进入输出函数后,它会从栈中找输出某个值,这里显然是数字1。

这就是为什么会输出a=1了,因为编译器根本没去找a的值,因为a是const int型,编译器认为它的内容不会变,所以干吗非得去内存中找啊,多麻烦,直接把值放到code里输出不就行了!

从某种意义上来说,const 相当于宏定义,但是程序为变量分配了存储空间,这样就可以进行类型检查。所以说很多 C++ 书籍作者提倡用 const 来代替 define,而且反对对 const 做 cast。就算要做 cast,也请尽量使用 C++ 的 cast 而不是 C 的类型转换。

恶劣的编程风格会带来不可预测的后果。类型转换之类的C留下来的习惯在编写高效率的程序时候是很有用的,但一定要确保知道采用这种方式会产生什么结果再去使用。对于那些 undefined 和 deprecated 的东西可以去利用,但是脑子中一定要有 idea。

[转载]const_cast的更多相关文章

  1. c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast  [版权声明]转载请注明出处 http://www.cnblogs.c ...

  2. C++学习笔记【转载】

    转载自:http://www.cnblogs.com/maowang1991/p/3290321.html 1.struct成员默认访问方式是public,而 class默认访问方式是private! ...

  3. 不可不表的OSG智能指针之强指针与弱指针 《转载》

    不可不表的OSG智能指针之强指针与弱指针 <转载> 使用OSG的人都知道OSG的内存管理方式采用了智能指针,通过智能指针的方式让OSG自己处理对象的销毁工作.在OSG中有两个智能指针类型, ...

  4. 四种强制类型转换的总结(const_cast、static_cast、dynamic_cast、reinterpreter_cast)

    四种强制类型转换的总结(const_cast.static_cast.dynamic_cast.reinterpreter_cast) 转载 2011年10月03日 23:59:05 标签: stru ...

  5. 转载 C++实现的委托机制

    转载 C++实现的委托机制 1.引言 下面的委托实现使用的MyGUI里面的委托实现,MyGUI是一款强大的GUI库,想理解更多的MyGUI信息,猛击这里http://mygui.info/ 最终的代码 ...

  6. 你也许还不知道const_cast,static_cast,dynamic_cast,reinterpret_cast的区别吧?

    [QQ群: 189191838,对算法和C++感兴趣可以进来]       开篇立意: C++中各种转换令人眼花缭乱,看似差不多,实际差很多,而且在当今时间,做一个"差不多先生"其 ...

  7. C++ 强制类型转换(转载)

    转载自:http://www.weixueyuan.net/view/6329.html 在C++语言中新增了四个关键字static_cast.const_cast.reinterpret_cast和 ...

  8. Crystal Clear Applied: The Seven Properties of Running an Agile Project (转载)

    作者Alistair Cockburn, Crystal Clear的7个成功要素,写得挺好. 敏捷方法的关注点,大家可以参考,太激动所以转载了. 原文:http://www.informit.com ...

  9. RTP与RTCP协议介绍(转载)

    RTSP发起/终结流媒体.RTP传输流媒体数据 .RTCP对RTP进行控制,同步.RTP中没有连接的概念,本身并不能为按序传输数据包提供可靠的保证,也不提供流量控制和拥塞控制,这些都由RTCP来负责完 ...

随机推荐

  1. vmstat uptime 系统状态脚本

    #!/bin/bash # # Command :vmstat,uptime #Capture_Stats - Gather System Performance Statistics ####### ...

  2. WP8 双击返回键退出

    bool isExit = false; // 构造函数 public MainPage() { InitializeComponent(); isExit = false; // 用于本地化 App ...

  3. C# Arraylist + struct 综合练习 枚举ENUE 递归

    枚举类型 一组常量的组合, 在不制定任何索引的情况下,默认第一个字段从0开始,之后的依次+1 在指定了某个索引的情况下,之后的依次+1 若之前定义的某字段的索引指向了之后的某个默认字段,那么他俩完全相 ...

  4. Android异步加载访问网络图片-解析json

    来自:http://www.imooc.com/video/7871 推荐大家去学习这个视频,讲解的很不错. 慕课网提供了一个json网址可以用来学习:http://www.imooc.com/api ...

  5. py随笔

    while true,无限循环 str.isdigit判断是不是数字 +只能在两个两个相同的类型之间执行 iter(i)将i加入迭代器

  6. python基础——迭代器

    python基础——迭代器 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str等: 一类是generator,包括生成器 ...

  7. DB2 嵌入式应用中定义游标(开放平台上)

    DECLARE CURSOR statement The DECLARE CURSOR statement defines a cursor. Invocation Although an inter ...

  8. Android Programming: Pushing the Limits -- Chapter 1: Fine-Tuning Your Development Environment

    ADB命令 Application Exerciser Monkey Gradle ProGuard 代码重用 版本控制 静态代码分析 代码重构 开发者模式   ADB命令: @.adb help:查 ...

  9. .net学习笔记---lambda表达式(自执行方法)

    http://www.cnblogs.com/jesse2013/p/happylambda.html#b034 lambda表达式 http://www.cnblogs.com/OceanEyes/ ...

  10. iis 7.5应用程序池自动停止

    今天在我的windows7旗舰版上配置iis7 (Internet Information Server)失败,一直未能启动服务,访问本地网络提示"Service Unavailable H ...