2 xtrtv xtrtv 于 2014.12.08 09:44 提问

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 的值到底有没有被改变?问什么同一个地址输出的值不一样?

8个回答

hudaweikevin
hudaweikevin   2014.12.08 10:57
已采纳

这里是编译器决定的,你用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),并不是按我们的惯性思维从地址里去取的。

xtrtv
xtrtv 哦明白了,多谢!
接近 3 年之前 回复
hudaweikevin
hudaweikevin 楼上91的试验更加证明了这一点,10应该是保存在一个栈里面的,直接取栈里的10运算的,而volatile就是从地址里面去取的,而实际上地址里的值确实是更新了的
接近 3 年之前 回复
hudaweikevin
hudaweikevin 楼上91的试验更加证明了这一点,10应该是保存在一个栈里面的,直接取栈里的10运算的,而volatile就是从地址里面去取的,而实际上地址里的值确实是更新了的
接近 3 年之前 回复
91program
91program   Ds   Rxr 2014.12.08 10:39

如果在 i 的定义前增加 volatile ,则可以看到最后的输入结果: i =11;

{
volatile const int i = 10;

    int *pi = const_cast<int *>(&i);
    ++*pi;
    TRACE("i = %d;@i = 0x%x\r\n",i,&i);
    TRACE("pi = %d,@pi = 0x%x\r\n",*pi,pi);

    TRACE("\r\n");
}

输出为:
i = 11;@i = 0x12edb0

pi = 11,@pi = 0x12edb0
以上为 VS2005 编译、运行的结果。

eagleyan
eagleyan   Rxr 2014.12.08 10:07

const_cast并不允许修改原来的常量值,c++里const_cast转换一个常量值的结果是未定义,i的值并不会改变,而pi里的值是个随机的值

91program
91program   Ds   Rxr 2014.12.08 10:18

从 VS2008 编译器的内存来看,这个地址 0x28ff44 的值已经是 11 了。

应该是 VS2008 等 编译器做了处理,i 是不可变的,在输出 i 时并没有从内存中去读取数据。

u010585135
u010585135   2014.12.08 10:37

变量i的值应该是不变的吧

w810443616
w810443616   2014.12.08 12:45

你的i地址发生了强制转换了。。。

tongyi78945
tongyi78945   2014.12.08 15:00

我将程序在vs2012和g++上都试了,它们结果一样的。很明显我们可以肯定,使用const_cast可以返回一个非常量指针指向常量。
并且可以改变常量的值,即原来存放该常量的地址的内容被改变。要确保不出错就应该使用对返回的指针的解引用,而不要再去使用原来存放常量的那个变量(常量)。

JohnPhan
JohnPhan   2014.12.09 13:50

如果const int i = 10;定义成全局的,或前缀static。您再如此这般的试一试。嘿嘿!

Csdn user default icon
上传中...
上传图片
插入图片