我正在尝试更改变量的值,该变量定义为int const,如下所示。
const int w = 10;
int* wp = const_cast <int*> (&w);
*wp = 20;
w的值没有改变,即使在赋值后也是10,尽管它表明好像w和wp都指向同一个内存位置。但是我可以更改w的值,如果在声明
时定义如下int i = 10;
const int w = i;
如果我改变i的声明,使其像
中那样使用constconst int i = 10;
w的值不会改变。
在第一种情况下,为什么w的值没有改变,即使w和wp指向相同的内存位置[这是我打印地址时的印象]
它对编译器的不同之处在于它对这两种情况的区别对待?
有没有办法确保w不会失去常数,无论它的定义方式如何?
答案 0 :(得分:15)
这是未定义const转换的情况之一,因为代码可能已经过优化,因此w实际上不是变量,并且在编译代码中并不存在。
尝试以下方法:
const volatile int w = 10;
int &wr = const_cast <int &> (w);
wr = 20;
std::cout << w << std::endl;
无论如何,我不会建议那样滥用const_cast。
答案 1 :(得分:8)
上例中的代码转换为以下汇编程序:
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
因为原始int i被声明为常量,所以编译器保留使用文字值而不是堆栈上存储的值的权利。这意味着该值不会被更改,您将无法使用原始的10。
故事的寓意是编译时常量应该保持不变,因为这是你告诉编译器的。故事的寓意是,为了改变常数而抛弃常数会导致坏事。
答案 2 :(得分:5)
const_cast
不会消除定义的变量的常量。如果您通过引用将非const变量传递给采用void foo(const int& x)
等const引用的方法,那么您可以使用const_cast
来修改x
中foo
的值},但仅当您实际传入的变量首先不是const时。
答案 3 :(得分:2)
为什么你不能重新绑定常量?而不是
const int w = 10;
int* wp = const_cast <int*> (&w);
*wp = 20;
// some code
只是引入具有相同名称的不同常量
const int w = 10;
{
const int w = 20;
// the same code
}
如果“new”常量应该取决于它自己的值,则应该引入另一个常量(const int _w = w; const int w = _w * 2;
)。不必要的任务将由编译器进行优化 - 因为我们已经看到它已经进行了这样的优化,因为这就是你提出问题的原因。
答案 4 :(得分:2)
您不应该更改const值。它是const的原因并且试图改变它很可能只会导致错误。如果const存储在只读存储器部分中,那么您将获得访问冲突。
答案 5 :(得分:1)
这是一个复习,应该注意这是在C中。这是使用const
关键字使用变量或指针的一个看似棘手的基础。这突出了指针变量foo
之间的区别,以及它的含义如何通过使用所述关键字来改变。
char const *foo; char * const foo; const char *foo;
第一个和最后一个声明,使'foo'指向的数据只读,但是,你可以改变'foo'指向的地址,例如。
const *char foo; /* OR char const *foo */ char str[] = "Hello"; foo = &str[0]; /* OK! */ foo[1] = 'h'; /* BZZZZTTT! Compile Fails! */
上面的中间声明,使指针只读,即你不能改变'foo'指向的数据的地址
char * const foo; char str[] = "Hello"; foo = &str[0]; /* BZZZZTTT! Compile Fails! */
答案 6 :(得分:1)
好问题。我认为混淆来自于C ++根据上下文使用关键字'const'作为两个不同的概念。这些概念是常量和只读变量。
当编译期间可以计算'const'变量的值时,它会创建一个真常量。无论何时使用,都会将对此类常量的引用替换为其值。这就是为什么内存中没有位置可以更改以影响使用它的所有位置。这就像使用#define。
在编译期间无法计算'const'变量的值时,它会创建一个只读变量。它在内存中有一个包含值的位置,但编译器强制执行只读行为。
答案 7 :(得分:0)
我的猜测是声明w const允许编译器执行更积极的优化,例如内联w的值和重新排序指令。 w似乎是否改变取决于在精确的情况下应用了哪些优化,并且不受您的控制。
你不能强迫w完全是const。 cons_cast应该向程序员暗示他们可能会做一些可疑的事情。