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. ffmpeg-20160803-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...

  2. Java for LintCode 链表插入排序

    用插入排序对链表排序 解题思路: 最省时间的方法是使用优先级队列,但是无法通过,那就直接插入排序好了. public ListNode insertionSortList(ListNode head) ...

  3. Games:取石子游戏(POJ 1067)

    取石子游戏 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 37662   Accepted: 12594 Descripti ...

  4. jquery after append appendTo三个函数的区别

    jq文档的说明是 1.after函数 定义和用法: after() 方法在被选元素后插入指定的内容. 语法: $(selector).after(content) 实例: <html> & ...

  5. MAC系统下配置环境变量

    环境变量初始值 /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin 使用export 可以设置暂时的环境变量 如果要追加PATH的话添加新的变量到文件中expor ...

  6. 【网络】ssl与ssh

    ssh(安全外壳协议):百度百科 ssl(安全套接字):http://kb.cnblogs.com/page/162080/ https应用了ssl协议 ssh与ssl的区别:http://blog. ...

  7. svn 默认忽略静态库 .a文件解决办法

    我也是在向SVN服务器上传文件时,遇到了这个问题,文件上传后,再下载后发现所有的.a文件全部丢失,后来才知道是上传文件的时候.a文件根本就没传上去,查找原因才知道上传的时候.a文件被过滤掉了,后来找到 ...

  8. asp.net 曲线图

    public void draw(DataTable dt) { //取得记录数量 int count = dt.Rows.Count; //记算图表宽度 int wd = 80 + 20 * (co ...

  9. 阿里云ecs Linux平台安装mongodb数据库

    MongoDB提供了linux平台上32位和64位的安装包,你可以在官网下载安装包. 下载地址:http://www.mongodb.org/downloads 下载完安装包,并解压 tgz(以下演示 ...

  10. STL_advance distance prev next

    template<class InputIterator> typename iterator_traits<InputIterator>::difference_type d ...