事情的起因呢,我就不说了,总之今天花了两个小时研究了一下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,这么强大的功能...还有对应的注释语句)看完了...我豁然开朗...也顿时无奈了...
代码
; 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
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!