在 C++ 中更改 const 变量的值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2006161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:49:34  来源:igfitidea点击:

changing the value of const variable in C++

c++const

提问by Narendra N

I am trying to change the value of a variable which is defined as int const as below.

我正在尝试更改定义为 int const 的变量的值,如下所示。

const int w = 10;
int* wp = const_cast <int*> (&w);
*wp = 20;

The value of w didn't change and was 10 even after the assignment, though it shows as if both w and wp are pointing to the same memory location. But I am able to the change the value of w, if defined as below while declaring

w 的值没有改变,即使在赋值之后也是 10,尽管它显示 w 和 wp 都指向相同的内存位置。但是我可以更改 w 的值,如果在声明时定义如下

int i = 10;
const int w = i;

If I change the declaration of i to make it const like in

如果我更改 i 的声明以使其像 in

const int i = 10;

The value of w doesn't change.

w 的值不会改变。

In the first case, how come the value of w didn't change, even though w and wp point to the same memory location [ that was my impression I get when I print their addresses ]

在第一种情况下,为什么 w 的值没有改变,即使 w 和 wp 指向相同的内存位置[这是我在打印它们的地址时得到的印象]

What difference it's to the compiler that it treats both the cases differently?

编译器对这两种情况的不同处理有什么区别?

Is there a way to make sure that w doesn't lose constness, irrespective of the way it is defined?

有没有办法确保 w 不会失去常量性,而不管它的定义方式如何?

回答by rmn

This is one of the cases where a const cast is undefined, since the code was probably optimized such that w isn't really a variable and does not really exist in the compiled code.

这是未定义 const 强制转换的情况之一,因为代码可能经过优化,因此 w 不是真正的变量,并且在编译的代码中并不真正存在。

Try the following:

请尝试以下操作:

const volatile int w = 10; 
int &wr = const_cast <int &> (w); 
wr = 20; 
std::cout << w << std::endl;

Anyhow, I would not advise abusing const_cast like that.

无论如何,我不建议像那样滥用 const_cast。

回答by doron

The code in the above example translates into the following assembler:

上面示例中的代码转换为以下汇编程序:

    movl    , 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    , (%eax) //*wp  = 20; -  so all good until here
    movl    , 4(%esp) //place constant value 10 onto the the stack for use in printf
    movl    $.LC0, (%esp) // load string
    call    printf //call printf

Because the original int i was declared constant, the compiler reserves the right to use the literal value instead of the value stored on the stack. This means that the value does not get changed and you are stuck with the original 10.

因为原始 int i 被声明为常量,编译器保留使用字面值而不是存储在堆栈中的值的权利。这意味着该值不会更改,并且您会使用原始的 10。

The moral of the story is compile time constants should remain constant because that is what you are telling the compiler. The moral of the story is that casting away constness in order to change a constant can lead to bad things.

这个故事的寓意是编译时常量应该保持不变,因为这就是你告诉编译器的。这个故事的寓意是为了改变一个常数而抛弃常数会导致坏事。

回答by Dave

const_castdoesn't take away the const-ness of a variable as defined. If you were to pass a non-const variable by reference in to a method taking a const reference like void foo(const int& x)then you could use const_castto modify the value of xwithin foo, but only if the variable you actually passed in was not const in the first place.

const_cast不会消除定义的变量的常量性。如果你要在路过参考非const变量取像一个const引用的方法void foo(const int& x),那么你可以使用const_cast修改的值x之内foo,但前提是你实际上是在传递的变量不是常量摆在首位。

回答by user230821

You should not being changing the const value. There is a reason it is const and trying to change it will most likely just result in errors. If the const is stored in a read only memory section then you will get access violations.

您不应该更改 const 值。它是 const 是有原因的,尝试更改它很可能只会导致错误。如果 const 存储在只读存储器部分,那么您将遇到访问冲突。

回答by P Shved

Why can't you just re-bind the constant? So instead of

为什么你不能重新绑定常量?所以代替

const int w = 10;
int* wp = const_cast <int*> (&w);
*wp = 20;
// some code

just introduce the different constant with the same name

只需引入具有相同名称的不同常量

const int w = 10;
{
   const int w = 20;
   // the same code
}

If the "new" constant should depend on its own value, you should introduce another constant (const int _w = w; const int w = _w * 2;). The unnecessary assignments will be optimized out by compiler--because we've seen it has done such optimisation, as it's the reason why you asked your question.

如果“新”常量应该依赖于它自己的值,你应该引入另一个常量 ( const int _w = w; const int w = _w * 2;)。不必要的赋值会被编译器优化掉——因为我们已经看到它做了这样的优化,因为这就是你问你问题的原因。

回答by t0mm13b

Here's a refresher, it should be noted that this is in C. This is a deceptively tricky underpinnings of the usage of a variable or pointer using the constkeyword. This highlights the difference between the pointer variable fooand how the meaning of it can change by using the said keyword.

这是一个复习,应该注意这是在 C 中。这是使用const关键字的变量或指针使用的一个看似棘手的基础。这突出了指针变量之间的区别foo以及它的含义如何通过使用上述关键字来改变。

char const *foo;

char * const foo;

const char *foo;

The first and last declarations, makes the data pointed to by ‘foo' read-only, but, you can change the address pointed to by ‘foo' e.g.

第一个和最后一个声明使'foo' 指向数据只读,但是,您可以更改 'foo' 指向的地址,例如

const *char foo; /* OR char const *foo */

char str[] = "Hello";

foo = &str[0]; /* OK! */

foo[1] = 'h'; /* BZZZZTTT! Compile Fails! */

The middle declaration in the above, makes the pointer read-only, i.e. you cannot change the address of the data pointed to by ‘foo'

上面的中间声明,使指针只读,即你不能改变'foo'指向的数据的地址

char * const foo;

char str[] = "Hello";

foo = &str[0]; /* BZZZZTTT! Compile Fails! */

回答by Dennis

Good question. I think the confusion comes from the fact that C++ uses the keyword ‘const' for two different concepts depending on the context. These concepts are constant and read-only variables.

好问题。我认为混淆来自这样一个事实,即 C++ 根据上下文将关键字“const”用于两个不同的概念。这些概念是常量和只读变量。

When a value of a ‘const' variable can be calculated during the compilation, it creates a true constant. References to such constant are replaced with its value whenever it is used. That's why there is no location in the memory that can be changed to affect all places where it is used. It is like using #define.

当可以在编译期间计算“const”变量的值时,它会创建一个真正的常量。每当使用此类常量时,对此类常量的引用都会替换为其值。这就是为什么内存中没有可以更改以影响使用它的所有位置的位置的原因。这就像使用#define。

When value of a ‘const' variable cannot be calculated during the compilation, it creates a read-only variable. It has a location in the memory that contains a value but compiler enforces a read-only behavior.

当在编译期间无法计算“const”变量的值时,它会创建一个只读变量。它在内存中有一个包含值的位置,但编译器强制执行只读行为。

回答by Zen

My guess would be that declaring w const allows the compiler to perform more aggressive optimizations such as inlining w's value and reordering instructions. Wether w appears to change or not depends on which optimizations were applied in the precise case and is not under your control.

我的猜测是声明 w const 允许编译器执行更积极的优化,例如内联 w 的值和重新排序指令。w 是否会发生变化取决于在具体情况下应用了哪些优化,并且不受您的控制。

You can't force w to be totally const. The cons_cast should be a hint to the programmer that they might be doing something fishy.

你不能强迫 w 完全是 const。cons_cast 应该暗示程序员他们可能正在做一些可疑的事情。