const仅对编译器有效。
严格来说,const不是“不可修改”,而是告诉编译器:我的程序不应该去修改。
如果编译器发现程序企图修改这个变量,就会报错。
至于隐式的修改,一般是由于一些不规范的代码引起的(如char * p = "abcde")。有的编译器把常量放入只读内存页,只要修改,硬件就会报一个异常,导致程序崩溃。但是有些编译器不会把他们放入只读内存页,这种情况下什么错误都不会遇到,除了忽然发现程序出现许多意想不到的错误而永远找不到原因。
在代码中,对简单类型的对象可能会 直接优化成立即数:
const int j=100;
int *p=const_cast(&j);
*p=200;
cout<<
输出为什么是100呢?cout<<*p<
编译器在优化代码时把cout<<<100了,所以虽然p和&j的值一样,但cout<
这是因为,const型在压栈时,是使用的直接的数,就有点像C的#define a 100
对于非系统缺省类型,系统不知道怎么去直接替换,因此必须占据内存。
-------------------------------
代码:
#include
using namespace std;
struct A
{
int i;
char ch;
A()
{
i = 100;
ch = 'S';
}
};
int main()
{
const A a;
const int i = 200;
int *p1 = (int*)&a.i;
int *p2 = (int*)&i;
*p1 = 1;
*p2 = 2;
// a.i = 200; //报错,左值不能为const
cout << a.i << " " << a.ch << endl;
cout << i << endl;
return 0;
}
运行结果:
1 S
200
内存:
0012FF74 02 00 00 00 01 00 ...... ;i的值已经被修改为2(未修改前是200),a.i的值被修改为1(未修改前是100)
0012FF7A 00 00 53 CC CC CC ..S烫. ;53是字符'S'
内存的值被修改而结果中却没有显示出来,因为const int类型被编译器优化为立即数,而结构体A编译器优化不了……
反汇编代码:
19: const A a;
00401598 8D 4D F8 lea ecx,[ebp-8]
0040159B E8 DC FB FF FF call @ILT+375(A::A) (0040117c)
20: const int i = 200;
004015A0 C7 45 F4 C8 00 00 00 mov dword ptr [ebp-0Ch],0C8h
21: int *p1 = (int*)&a.i;
004015A7 8D 45 F8 lea eax,[ebp-8]
004015AA 89 45 F0 mov dword ptr [ebp-10h],eax
22: int *p2 = (int*)&i;
004015AD 8D 4D F4 lea ecx,[ebp-0Ch]
004015B0 89 4D EC mov dword ptr [ebp-14h],ecx
23:
24: *p1 = 1;
004015B3 8B 55 F0 mov edx,dword ptr [ebp-10h]
004015B6 C7 02 01 00 00 00 mov dword ptr [edx],1
25: *p2 = 2;
004015BC 8B 45 EC mov eax,dword ptr [ebp-14h]
004015BF C7 00 02 00 00 00 mov dword ptr [eax],2
26: // a.i = 200;
27: cout << a.i << " " << a.ch << endl;
004015C5 68 C8 10 40 00 push offset @ILT+195(std::endl) (004010c8)
004015CA 8A 4D FC mov cl,byte ptr [ebp-4]
004015CD 51 push ecx
004015CE 68 1C C0 46 00 push offset string " " (0046c01c)
004015D3 8B 55 F8 mov edx,dword ptr [ebp-8]
004015D6 52 push edx
004015D7 B9 E0 77 47 00 mov ecx,offset std::cout (004777e0)
004015DC E8 1E FB FF FF call @ILT+250(std::basic_ostream >::operator<<) (004010ff)
004015E1 50 push eax
004015E2 E8 A8 FC FF FF call @ILT+650(std::operator<<) (0040128f)
004015E7 83 C4 08 add esp,8
004015EA 50 push eax
004015EB E8 D2 FB FF FF call @ILT+445(std::operator<<) (004011c2)
004015F0 83 C4 08 add esp,8
004015F3 8B C8 mov ecx,eax
004015F5 E8 F0 FB FF FF call @ILT+485(std::basic_ostream >::operator<<) (004011ea)
28: cout << i << endl;
004015FA 68 C8 10 40 00 push offset @ILT+195(std::endl) (004010c8)
004015FF 68 C8 00 00 00 push 0C8h
00401604 B9 E0 77 47 00 mov ecx,offset std::cout (004777e0)
00401609 E8 F1 FA FF FF call @ILT+250(std::basic_ostream >::operator<<) (004010ff)
0040160E 8B C8 mov ecx,eax
00401610 E8 D5 FB FF FF call @ILT+485(std::basic_ostream >::operator<<) (004011ea)
-------------参考--------------
http://dev.chinaitzhe.com/c/2008-09/1222078066109523.html
http://forum.eviloctal.com/thread-39463-1-1.html (除了const的还有static,等有空了解一下……)
http://www.diybl.com/course/3_program/c++/cppjs/20091112/182222.html (有一些以前没注意到的const细节)
-------------------------------
忘了是在哪篇面经里看到一个问题:
java的const(貌似是final,对java不了解,汗)和c++的const各是怎么实现的?要不就是它们的区别是什么?(忘了是不是这样的问题)