读书人

C++ 关于const的有关问题

发布时间: 2013-03-12 11:19:35 作者: rapoo

C++ 关于const的问题
int main()
{
const int i = 100;
const int *p = &i;
int *q = (int *)p;
*q = 200;
cout<<*q<<" "<<i<<endl;
cout<<q<<" "<<&i<<endl;
cout<<*q<<" "<<*p<<" "<<*(&i)<<endl;
return 0;
}

打印出来的值出人意料:
200 100
0012FF60 0012FF60
200 200 100

根据*p和*q的值看,i的值应该被改成200了,为什么打印出来的i值还是100。为了防止i是从寄存器取出来的,使用*(&i)读内存中的值也还是100。同一块内存地址读出来的数据怎么不一样?
[解决办法]
对,很可能是编译器优化的结果。
[解决办法]
在未优化编译的情况下,对于拥有const属性的i,编译器虽然为i分配了空间,但使用时,除非必要(比如取地址),是直接取其值100。
*(&i)被简化为i后,就直接取其值100用于cout输出了,
具体可参考下汇编源码

[解决办法]
我把你的程序简化了一下
intmain()
{
const int i = 100;
const int *p = &i;
int *q = (int *)p;
*q = 200;
//cout<<*q<<" "<<i<<endl;
//cout<<q<<" "<<&i<<endl;
cout<<*q<<" "<<*p<<" "<<*(&i)<<endl;

return0;
}

下面是对应的汇编代码,未优化
_main:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 83 EC 0C sub esp,0Ch
00000006: C7 45 F4 64 00 00 mov dword ptr [ebp-0Ch],64h //这里为i分配空间并赋值100
00
0000000D: 8D 45 F4 lea eax,[ebp-0Ch]
00000010: 89 45 FC mov dword ptr [ebp-4],eax
00000013: 8B 4D FC mov ecx,dword ptr [ebp-4]
00000016: 89 4D F8 mov dword ptr [ebp-8],ecx
00000019: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000001C: C7 02 C8 00 00 00 mov dword ptr [edx],0C8h
00000022: 68 00 00 00 00 push offset ?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z


00000027: 6A 64 push 64h //这里直接将i也就是100亚入堆栈
00000029: 68 00 00 00 00 push offset $SG40957
0000002E: 8B 45 FC mov eax,dword ptr [ebp-4]
00000031: 8B 08 mov ecx,dword ptr [eax]
00000033: 51 push ecx
00000034: 68 00 00 00 00 push offset $SG40958
00000039: 8B 55 F8 mov edx,dword ptr [ebp-8]
0000003C: 8B 02 mov eax,dword ptr [edx]
0000003E: 50 push eax
0000003F: B9 00 00 00 00 mov ecx,offset ?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
00000044: E8 00 00 00 00 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
00000049: 50 push eax
0000004A: E8 00 00 00 00 call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
0000004F: 83 C4 08 add esp,8
00000052: 8B C8 mov ecx,eax
00000054: E8 00 00 00 00 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z
00000059: 50 push eax
0000005A: E8 00 00 00 00 call ??$?6U?$char_traits@D@std@@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@PBD@Z
0000005F: 83 C4 08 add esp,8
00000062: 8B C8 mov ecx,eax
00000064: E8 00 00 00 00 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@H@Z


00000069: 8B C8 mov ecx,eax
0000006B: E8 00 00 00 00 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z
00000070: 33 C0 xor eax,eax
00000072: 8B E5 mov esp,ebp
00000074: 5D pop ebp
00000075: C3 ret


注意00000027:这一行,是直接push 64h,而没有提取程序为i分配的空间[ebp-0ch]的值


[解决办法]
编译器知道const的哪些地方的用法,会对其进行优化。

const int i = 100;
cout << i << endl; // 在这里用,直接用100代替
cout << *(&i) << endl; // 在这里有使用,也直接用100代替

另外C++当中不提倡int *p = (int*)q这种转换,int *p = const_cast<int*>(q),会好看一点。
[解决办法]
另外简单的变量,表达式之类的,有时也会优化掉

int add(int x,int y)
{
int z=x+y;
return z;
}
int main(){
int x=10;
int y=100;
printf("%d",add(x,y));

return 0;
}
会变成
int main(){

printf("%d",110);//这个优化叫常量代换。

return 0;
}


读书人网 >C++

热点推荐