• 慎用const_cast


    转自:http://blog.solrex.cn/articles/%E6%85%8E%E7%94%A8const_cast.html

    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。

  • 相关阅读:
    470. 用 Rand7() 实现 Rand10() 采样
    165. 比较版本号 字符串
    Java 通过属性名称读取或者设置实体的属性值
    双非Java的学习之旅以及秋招路程
    【Unity3D】不可读Texture资源的获取
    java 8 Map 之merge用法
    Jmeter-计数器的应用
    Jmeter-集合点【同步定时器】应用
    2. Go并发编程--GMP调度
    Go序列化嵌套结构体
  • 原文地址:https://www.cnblogs.com/nsnow/p/1486486.html
Copyright © 2020-2023  润新知