当前所在位置:珠峰网资料 >> 计算机 >> 计算机等级考试 >> 正文
C++constconst_cast行为分析
发布时间:2010/5/20 14:59:09 来源:城市学习网 编辑:ziteng
  事情的起因呢,我就不说了,总之今天花了两个小时研究了一下C++中的const const_cast行为,发现与原先预想的很不一样...
  先看一段代码:
  const
  #include <stdio.h>
  int main()
  {
  const int a=2;
  const int * b=&a;
  printf("%d, %d, %d, %d\n", a, *b, &a, b);
  int * c=const_cast<int *>(b);
  printf("%d, %d\n", *c, c);
  *c=4;
  printf("%d, %d, %d, %d, %d, %d\n", a, &a, *b, b, *c, c);
  const int e=a;
  printf("%d, %d, %d, %d\n", e, &e,  &a, *(&a));
  int d=(int)&a;
  printf("%d, %d, %d, %d, %d\n", a, &a, d, &d, *(int *)d);
  const int * f=&a;
  printf("%d, %d\n", *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
  请按任意键继续. . . [NextPage]   很明显...凡是输出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,这么强大的功能...还有对应的注释语句)看完了...我豁然开朗...也顿时无奈了...
  代码
  ; 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, %d\n", 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, %d\n", *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, %d\n", 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
 [NextPage]   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, %d\n", 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, %d\n", 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, %d\n", *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...
广告合作:400-664-0084 全国热线:400-664-0084
Copyright 2010 - 2017 www.my8848.com 珠峰网 粤ICP备15066211号
珠峰网 版权所有 All Rights Reserved