当我编写这个代码片段时,在通过指针修改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
任何人都可以提供帮助。
答案 0 :(得分:3)
您的代码只是具有未定义的行为:您不能修改常量对象,并且const_cast
允许您违反该行为(这就是为什么它基本上从不使用{的好主意{1}},极少数且非常罕见的例外情况)。因此,询问代码中断的特定方式的原因和方法几乎没有什么用处。但是如果你必须知道,常量积分表达式通常会按值被折叠到它们被引用的位置,这看起来就像你的情况中发生的那样。
答案 1 :(得分: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
除了少数例外情况是个坏主意。