我试图更改一个变量的值,该变量定义为int const,如下所示.
const int w = 10;
int* wp = const_cast <int*> (&w);
*wp = 20;
Run Code Online (Sandbox Code Playgroud)
w的值没有改变,即使在赋值之后仍然是10,尽管它表明w和wp都指向同一个内存位置.但是我可以更改w的值,如果在声明时定义如下
int i = 10;
const int w = i;
Run Code Online (Sandbox Code Playgroud)
如果我改变i的声明使其成为常量
const int i = 10;
Run Code Online (Sandbox Code Playgroud)
w的值不会改变.
在第一种情况下,为什么w的值没有改变,即使w和wp指向相同的内存位置[这是我打印地址时的印象]
与编译器有什么不同,它以不同的方式处理这两种情况?
有没有办法确保w不会失去常数,无论它的定义方式如何?
rmn*_*rmn 15
这是const cast未定义的情况之一,因为代码可能已经过优化,因此w实际上不是变量,并且在编译的代码中并不存在.
请尝试以下方法:
const volatile int w = 10;
int &wr = const_cast <int &> (w);
wr = 20;
std::cout << w << std::endl;
Run Code Online (Sandbox Code Playgroud)
无论如何,我不建议那样滥用const_cast.
上例中的代码转换为以下汇编程序:
movl $10, 28(%esp) //const int i = 10;
leal 28(%esp), %eax //int* wp = const_cast <int*>(&i);
movl %eax, 24(%esp) //store the pointer on the stack
movl 24(%esp), %eax //place the value of wp in eax
movl $20, (%eax) //*wp = 20; - so all good until here
movl $10, 4(%esp) //place constant value 10 onto the the stack for use in printf
movl $.LC0, (%esp) // load string
call printf //call printf
Run Code Online (Sandbox Code Playgroud)
因为原始int i被声明为常量,所以编译器保留使用文字值而不是存储在堆栈上的值的权利.这意味着该值不会被更改,并且您仍然坚持原始10.
故事的寓意是编译时常量应该保持不变,因为这是你告诉编译器的.故事的寓意是,为了改变常数而抛弃常数会导致坏事.
const_cast不会消除定义的变量的常量.如果你要在路过参考非const变量取像一个const引用的方法void foo(const int& x),那么你可以使用const_cast修改的值x之内foo,但前提是你实际上是在传递的变量在第一个地方是不是const的.