C++如何保持const值?

Jos*_*Shi 3 c++ compiler-optimization

#include <iostream>
using namespace std;
int main() {
    const int a = 10;
    auto *b = const_cast<int *>(&a);
    *b = 20;
    cout << a << " " << *b;
    cout << endl << &a << " " << b;
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

10 20
0x7ffeeb1d396c 0x7ffeeb1d396c
Run Code Online (Sandbox Code Playgroud)

a*b是在同一个地址,为什么他们有不同的价值?

use*_*447 9

很可能这是由优化引起的.

正如molbdnilo在他的评论中已经说过:"编制者盲目地信任你.如果你骗他们,可能会发生奇怪的事情."

因此,当启用优化时,编译器会找到声明

const int a = 10;
Run Code Online (Sandbox Code Playgroud)

并且认为"啊,这永远不会改变,所以我们不需要一个"真正的"变量,并且可以a简单地用10" 替换代码中的所有外观.此行为称为常量折叠.

现在在下一行你"欺骗"编译器:

auto *b = const_cast<int *>(&a);
*b = 20;
Run Code Online (Sandbox Code Playgroud)

并改变了,虽然你已经答应不这样做.结果是混乱.

就像很多人已经提到的那样,Christian Hackl在他出色的深入答案中进行了彻底的分析,这是不确定的行为.通常允许编译器对显式声明的常量应用常量折叠const.

你的问题是一个非常好的例子(我不知道怎么会有人投票!)为什么const_cast非常危险(当与原始指针结合使用时更多),应该只在绝对必要时使用,并且应该至少彻底评论为什么它被使用,如果它是不可避免的.在这种情况下,评论很重要,因为它不仅是你"欺骗"的编译器:

您的同事也将依赖这些信息,const并依赖于它不会改变的信息.如果它虽然改变了,你没有通知他们,也没有发表评论,也不知道你在做什么,你将在工作中度过糟糕的一天:)

试试看:或许你的程序甚至会表现在调试版本(不优化)不同,发布版本(优化),以及这些错误通常是非常恼人修复.

  • 很好,最后一些信息实际上有帮助,而不仅仅是说它是错的. (3认同)
  • 我不认为这个答案提供了足够的信息,因为它既没有提到"不断折叠"也没有提到"未定义的行为". (2认同)