0

当我编写此代码片段时,在通过指针修改 const 变量 i 的值后,我将 i 的值设为 10,但是当我打印 *ptr 时,我得到 110。

const int i = 10;
int *ptr = const_cast<int *>(&i);
*ptr = *ptr + 100;
cout << "i:     " << i << "\t*ptr:      " << *ptr << endl;

我得到输出 i: 10 和 *ptr :110。

在这种情况下,我有一个 const 变量 x 作为 Base 类的成员变量。通过函数 show() 我可以修改 const 变量 x 的值,即当我打印 x 和 *ptr 时,我在两者中都得到了改变的值。

class Base
{
public:
const int x;
Base(int i) : x(i) {}
virtual void show()
{
            int *ptr = const_cast<int *>(&x);        
            int *ptr = const_cast<int *>(&x);
            cout << "In Base show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};

class Derived : public Base
{
    public:
    Derived(int i) : Base(i){}
    virtual void show()
    {
            int *ptr = const_cast<int *>(&x);
            cout << "In Derived show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};
int main()
{
    Base bobj(5),*bp;
    Derived dobj(20), *dptr;
    bp = &bobj;
    bp->show();
    bp = &dobj;
    bp->show();
    return 0;
}


The output which I am getting is this 
In Base show:
Address of x    :   0x7fff82697588
Address in ptr  :   0x7fff82697588
value in x          :   5
value in ptr    :   5
After modifying 
value in x          :   15
value in ptr    :   15

In Derived show:
Address of x        :       0x7fff82697578
Address in ptr      :   0x7fff82697578
value in x          :       20
value in ptr        :       20
After modifying 
value in x          :       30
value in ptr        :       30

任何人都可以帮忙。

4

2 回答 2

3

您的代码只是具有未定义的行为:您不得修改常量对象,并且您const_cast允许您违反它(这就是为什么使用 基本上从来都不是一个好主意const_cast,只有极少数和非常罕见的例外)。因此,询问代码中断的特定方式的原因和方式没有什么意义。但是,如果您必须知道,常量积分表达式通常会按值折叠到它们被引用的地方,这看起来就像您的情况一样。

于 2013-05-09T08:25:06.233 回答
1

原因是您的编译器i在编译此行时已将 的值内联到代码中:

cout << "i: " << i << "\t*ptr: " << *ptr << endl;

因为i是一个const变量,所以编译器已经优化了代码,将i上面的行替换为10. 如果我们查看生成的程序集(我使用的是 VS2010):

002314F2  mov         ecx,dword ptr [ptr]  // ptr is being pushed here (110)
002314F5  mov         edx,dword ptr [ecx]  
002314F7  push        edx  
002314F8  push        offset string "\t*ptr:      " (23783Ch)     
002314FD  mov         ebx,esp  
002314FF  push        0Ah  //  0Ah is being pushed here (A is hex for 10)
00231501  push        offset string "i:     " (237830h) 

发生的事情是您修改了内存中的常量,但生成的程序集实际上并未使用内存地址 - 它只是输出“10”,而不管内存中有什么。

正如 Kerrek 所说,这是未定义的行为,因此其他编译器可能会做一些与此完全不同的事情。

一般来说,在const_cast少数例外情况下使用是个坏主意。

于 2013-05-09T09:08:51.733 回答