问题描述
- c++用关于const变量的疑问
-
首先看下面一段代码:#include <iostream> using namespace std; int main() { const int i = 10; int *pi = const_cast<int *>(&i); ++*pi; cout << " i = " << i << ", @" << &i << endl; cout << "*pi = " << *pi << ", @" << pi << endl; }
运行结果是:
i = 10, @0x28ff44
*pi = 11, @0x28ff44
我想问的是,变量 i 的值到底有没有被改变?问什么同一个地址输出的值不一样?
解决方案
这里是编译器决定的,你用VS2008调试就会发现,i的值在调试窗口里都是变化了的。但是const表示的是一个常量,不可变的,如果用const-cast又可将它改变,就自相矛盾了。
于是编译器采取了一种方案,在汇编里可以看出端倪:
cout << " i = " << i << ", @" << &i << endl;
004142B8 mov esi,esp
004142BA mov eax,dword ptr [__imp_std::endl (41A348h)]
004142BF push eax
004142C0 mov edi,esp
004142C2 lea ecx,[i]
004142C5 push ecx
004142C6 push offset string ", @" (417880h)
004142CB mov ebx,esp
004142CD push 0Ah
004142CF push offset string " i = " (417878h)
004142D4 mov edx,dword ptr [__imp_std::cout (41A34Ch)]
004142DA push edx
10是直接使用的(见上面的push 0Ah),并不是按我们的惯性思维从地址里去取的。
解决方案二:
如果在 i 的定义前增加 volatile ,则可以看到最后的输入结果: i =11;
{
volatile const int i = 10;
int *pi = const_cast<int *>(&i);
++*pi;
TRACE("i = %d;@i = 0x%xrn",i,&i);
TRACE("pi = %d,@pi = 0x%xrn",*pi,pi);
TRACE("rn");
}
输出为:
i = 11;@i = 0x12edb0
pi = 11,@pi = 0x12edb0
以上为 VS2005 编译、运行的结果。
解决方案三:
const_cast并不允许修改原来的常量值,c++里const_cast转换一个常量值的结果是未定义,i的值并不会改变,而pi里的值是个随机的值
解决方案四:
从 VS2008 编译器的内存来看,这个地址 0x28ff44 的值已经是 11 了。
应该是 VS2008 等 编译器做了处理,i 是不可变的,在输出 i 时并没有从内存中去读取数据。
解决方案五:
变量i的值应该是不变的吧
解决方案六:
你的i地址发生了强制转换了。。。
解决方案七:
我将程序在vs2012和g++上都试了,它们结果一样的。很明显我们可以肯定,使用const_cast可以返回一个非常量指针指向常量。
并且可以改变常量的值,即原来存放该常量的地址的内容被改变。要确保不出错就应该使用对返回的指针的解引用,而不要再去使用原来存放常量的那个变量(常量)。
解决方案八:
如果const int i = 10;定义成全局的,或前缀static。您再如此这般的试一试。嘿嘿!