C++ const const_cast 行为分析

事情的起因呢,我就不说了,总之今天花了两个小时研究了一下C++中的const const_cast行为,发现与原先预想的很不一样...

先看一段代码:

C++ const const_cast 行为分析C++ const const_cast 行为分析const

#include <stdio.h>int main(){    const int a=2;    const int * b=&a;    printf("%d, %d, %d, %dn", a, *b, &a, b);    int * c=const_cast<int *>(b);    printf("%d, %dn", *c, c);    *c=4;    printf("%d, %d, %d, %d, %d, %dn", a, &a, *b, b, *c, c);    const int e=a;    printf("%d, %d, %d, %dn", e, &e,  &a, *(&a));    int d=(int)&a;    printf("%d, %d, %d, %d, %dn", a, &a, d, &d, *(int *)d);    const int * f=&a;    printf("%d, %dn", *f, f);}

过客们知道其中玄机的可以忽略本文,不知道的可以先想一想预想的结果...再运行一下...看一下实际的结果...

大体的意思呢,就是我申明了一个int类型的const变量...

然后呢用const_cast 将const属性去掉了,再去输出其值...看一下结果...预想的结果,凡是输出a的地方,应该都变成了4...

实际上...结果是这个样子的...

2, 2,2423784,2423784

2,2423784

2,2423784, 4,2423784, 4,2423784

2, 2423748,2423784,2

2,2423784,2423784, 2423736, 4

4,2423784

请按任意键继续. . .

很明显...凡是输出a的地方...都变成了2...(蓝色即为a的地址,红色为我幻想着为4实际上为2的a的值...)当然我不死心...这是在VS2010下的结果...放到RedHat GCC下编译运行...幻想着我找到了VC的bug了...发现结果...和VC是一样的...

我迷失了...调试内存...发现a的那块地址...的的确确千真万确...变成了4...我怒了...

翻开C++ Primer Plus(第五版中文版) 585页 里面在描述const_cast的一段代码的时候,这么描述:“... ...调用change()时,修改了pop1,但没有修改pop2(在使用的编译器生成pop2的一个临时拷贝,并将地址赋给pc,但正如前面指出的,C++标准指出,在这种情况下,上述行为时不确定的)。”

这么一句话的意思是?当试图强制转换一个const变量时,会生成一个副本,保留原来的值?实际情况貌似不是这样的...我在内存里可找不到那个副本...

无奈之后,查看汇编后的代码...以下截取最重要的一部分(VC上编译开关加上/FAs,这么强大的功能...还有对应的注释语句)看完了...我豁然开朗...也顿时无奈了...

C++ const const_cast 行为分析C++ const const_cast 行为分析代码

; 5    : {    push    ebp    mov    ebp, esp    sub    esp, 264                ; 00000108H    push    ebx    push    esi    push    edi    lea    edi, DWORD PTR [ebp-264]    mov    ecx, 66                    ; 00000042H    mov    eax, -858993460                ; ccccccccH    rep stosd; 6    :     const int a=2;    mov    DWORD PTR _a$[ebp], 2; 7    :     const int * b=&a;    lea    eax, DWORD PTR _a$[ebp]    mov    DWORD PTR _b$[ebp], eax; 8    :     printf("%d, %d, %d, %dn", a, *b, &a, b);    mov    esi, esp    mov    eax, DWORD PTR _b$[ebp]    push    eax    lea    ecx, DWORD PTR _a$[ebp]    push    ecx    mov    edx, DWORD PTR _b$[ebp]    mov    eax, DWORD PTR [edx]    push    eax    push    2    push    OFFSET ??_C@_0BA@IJNICBJ@?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 20                    ; 00000014H    cmp    esi, esp    call    __RTC_CheckEsp; 9    :     int * c=const_cast<int *>(b);    mov    eax, DWORD PTR _b$[ebp]    mov    DWORD PTR _c$[ebp], eax; 10   :     printf("%d, %dn", *c, c);    mov    esi, esp    mov    eax, DWORD PTR _c$[ebp]    push    eax    mov    ecx, DWORD PTR _c$[ebp]    mov    edx, DWORD PTR [ecx]    push    edx    push    OFFSET ??_C@_07MHMABKGB@?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 12                    ; 0000000cH    cmp    esi, esp    call    __RTC_CheckEsp; 11   :     *c=4;    mov    eax, DWORD PTR _c$[ebp]    mov    DWORD PTR [eax], 4; 12   :     printf("%d, %d, %d, %d, %d, %dn", a, &a, *b, b, *c, c);    mov    esi, esp    mov    eax, DWORD PTR _c$[ebp]    push    eax    mov    ecx, DWORD PTR _c$[ebp]    mov    edx, DWORD PTR [ecx]    push    edx    mov    eax, DWORD PTR _b$[ebp]    push    eax    mov    ecx, DWORD PTR _b$[ebp]    mov    edx, DWORD PTR [ecx]    push    edx    lea    eax, DWORD PTR _a$[ebp]    push    eax    push    2    push    OFFSET ??_C@_0BI@HAFKFEEE@?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 28                    ; 0000001cH    cmp    esi, esp    call    __RTC_CheckEsp; 13   :     const int e=a;    mov    DWORD PTR _e$[ebp], 2; 14   :     printf("%d, %d, %d, %dn", e, &e,  &a, *(&a));    mov    esi, esp    push    2    lea    eax, DWORD PTR _a$[ebp]    push    eax    lea    ecx, DWORD PTR _e$[ebp]    push    ecx    push    2    push    OFFSET ??_C@_0BA@IJNICBJ@?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 20                    ; 00000014H    cmp    esi, esp    call    __RTC_CheckEsp; 15   :     int d=(int)&a;    lea    eax, DWORD PTR _a$[ebp]    mov    DWORD PTR _d$[ebp], eax; 16   :     printf("%d, %d, %d, %d, %dn", a, &a, d, &d, *(int *)d);    mov    esi, esp    mov    eax, DWORD PTR _d$[ebp]    mov    ecx, DWORD PTR [eax]    push    ecx    lea    edx, DWORD PTR _d$[ebp]    push    edx    mov    eax, DWORD PTR _d$[ebp]    push    eax    lea    ecx, DWORD PTR _a$[ebp]    push    ecx    push    2    push    OFFSET ??_C@_0BE@DHHNLGML@?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 24                    ; 00000018H    cmp    esi, esp    call    __RTC_CheckEsp; 17   :     const int * f=&a;    lea    eax, DWORD PTR _a$[ebp]    mov    DWORD PTR _f$[ebp], eax; 18   :     printf("%d, %dn", *f, f);    mov    esi, esp    mov    eax, DWORD PTR _f$[ebp]    push    eax    mov    ecx, DWORD PTR _f$[ebp]    mov    edx, DWORD PTR [ecx]    push    edx    push    OFFSET ??_C@_07MHMABKGB@?$CFd?0?5?$CFd?6?$AA@    call    DWORD PTR __imp__printf    add    esp, 12                    ; 0000000cH    cmp    esi, esp    call    __RTC_CheckEsp; 19   : }

看完了没...看完了估计你也懂了...汇编后...所有a的地方...统统都已经变成了 2 ...!!! 原来编译器是这么汇编的...

恩……总结一下...1 尽信书不如无书 2 实践是检验真理的唯一标准 3 没有调查就没有发言权 4 不要凭主观臆断 不要想当然 5...

完...
原文链接: https://www.cnblogs.com/Kingpro/archive/2010/05/18/const_cast.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/10966

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 上午12:33
下一篇 2023年2月7日 上午12:35

相关推荐