C++ 通过重复使用的非`const`名称修改动态分配的`const`对象是否合法?

C++ 通过重复使用的非`const`名称修改动态分配的`const`对象是否合法?,c++,c++11,constants,language-lawyer,const-correctness,C++,C++11,Constants,Language Lawyer,Const Correctness,考虑以下计划: #include <iostream> int main() { int x = 0; const int* px = new (&x) const int(0); x = 1; std::cout << *px; // 1? } #包括 int main() { int x=0; 常数int*px=新的(&x)常数int(0); x=1; std::couttl;dr:是的,这是未定义的行为。不,编译器不会诊断它。

考虑以下计划:

#include <iostream>

int main()
{
   int x = 0;
   const int* px = new (&x) const int(0);
   x = 1;
   std::cout << *px;  // 1?
}
#包括
int main()
{
int x=0;
常数int*px=新的(&x)常数int(0);
x=1;

std::couttl;dr:是的,这是未定义的行为。不,编译器不会诊断它。


一般来说,编译器不会(有时也不能)诊断UB。更明显的
const
-正确性冲突示例实际上是格式不正确的,并且:

因此,回到您的代码片段,我不会对编译器诊断有太多期望

尽管如此,您的代码仍会调用未定义的行为。让我们检查一下:

#include <iostream>

int main()
{
   int x = 0;
   const int* px = new (&x) const int(0);
   x = 1;
   std::cout << *px;  // 1?
}
#包括
int main()
{
int x=0;
常数int*px=新的(&x)常数int(0);
x=1;

std::cout“我看不出可能会执行哪些优化来破坏分配和后续读取”。我不知道你认为编译器有多聪明,但是:escape分析表明,
px
在初始化后不会被修改,它总是指向新的const对象。因此编译器可能会将
*px
视为对const的引用,并将
*px
的所有用法替换为
*px>的初始化值
,即
0
。这不会引起火山爆发,但编译器可能会这样做,或者实际上可能从最后一行的
*px
加载,这足以证明它是UB。@SteveJessop:面对在其他翻译单元中定义的可能的
运算符new
它能做到吗?哇,我的回滚/展开/r艾洛贝克不再崩溃了。哦,好吧。@Mattfillips:我不明白为什么我不能保持“提问者”/“回答者”的抽象。为什么它“令人讨厌”?因为这就好像你在假装有两个人参与了这条线索,而只有一个人,你?就好像你的问题被另一位专家认为是有趣的,足以引起深思熟虑的回答。事实并非如此,或者任何可能的答案都被你抢先了(在撰写本文时)有趣的是——我把Q和A都投了高票——但都是你。我的意思是,我不认为你真的想欺骗任何人,但直到最后我才有了错误的印象,所以:令人讨厌。就我个人而言,我不喜欢阅读评论中的元辩论。我们能不能坚持实质内容,把其他东西移到它该去的地方?你为什么不呢将此发布为社区维基而不是积分收割机??你有足够的积分,这似乎满足了一个人的自我。或者你正在计算等同于$$的积分?@DumbCoder:我写问题和答案是为了分享知识。我不明白为什么我不应该像对待任何独立问题或答案那样获得代表奖励!此外在,。我希望这能回答您的问题。@DumbCoder:community wiki不是为了逃避rep。它说,“community wiki在回答中的目的是帮助分担解决问题的负担”。在这种情况下,Lightness没有特别的理由让低rep用户可以编辑他的答案。@DumbCoder:
#include <iostream>

int main()
{
    const int x = 0;
    *const_cast<int*>(&x) = 1;
    std::cout << x;
}

// Output: 1
#include <iostream>

int main()
{
   int x = 0;
   const int* px = new (&x) const int(0);
   x = 1;
   std::cout << *px;  // 1?
}