const_cast 和射击自己的脚

const_cast and Shooting your own Foot

我意识到这会导致未定义的行为:

const int x = 12;
*const_cast<int*>(&x) = 13;

但是 gcc 是否采取了任何措施来防止它杀死你,或者它只是让你退后一步说 "Hey you know better"。

也许它只是默默地删除了整个程序中的 const 修饰符或其他东西(我不知道我只是在这里猜测)。

有什么想法吗?

事实上,你可以放弃指针的常量性:

5.2.11/7 Depending on the type of the object, a write operation through the pointer, lvalue or pointer to data member resulting from a const_cast that casts away a const-qualifier may produce undefined behavior

如果引用的对象是常量,这是未定义的行为

7.1.6.1/4: Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

未定义的行为是...未定义:

1.3.24: behavior for which this International Standard imposes no requirements (...) Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

所以,让我们想象一下会发生什么:可能会工作,可能会出现段错误(例如,因为 const 数据将存储在 const 内存段中),可能不会按预期工作(例如,写入被忽略),您可能会在编译时收到警告或错误。所以最好避免这种情况!

每日名言: "C 很容易搬起石头砸自己的脚;C++ 让它变得更难,但当你这样做时,它会毁了你的整个断腿" - Bjarne Stroustrup

gcc 以在遇到 UB 时定期更改实际行为而闻名。版本 1 尝试 运行 nethack,然后打印“99 bottles”。我记得在某个时刻,当 gcc 开始优化代码中的离开条件时,Linux 内核中出现了一个关键漏洞

int x = s->x;
if(s != NULL) {

因为它假设当你取消引用一个指针时,你知道它是非空的(否则它是标准的 UB)。

未定义行为的部分要点是允许编译器做任何事情。我会让其他人引用标准语,并专注于你问题中的哲学。

一般来说,声明一个变量 const,丢弃 constness,然后做一些修改 const 变量的事情是编译器不会特别做任何事情的一个领域保护你 - 毕竟,如果你正在做这样的事情,你可能会有很多不同的想法,编译器(或开发它的程序员)没有理由假设其中任何一个。

在您的示例中,定义 x 的代码(与仅声明它不同)可能与使用 const_cast 修改它的代码位于不同的编译单元中。 (这取决于声明、定义和代码在源文件中的组织方式)。

gcc 是一种编译器,大多数情况下,除了它正在编译的项目之外,它不会进入项目的编译单元。这意味着它通常无法检测此类情况,也无法确保一个编译单元中发生的事情与另一个编译单元中发生的事情一致(即以保护您的方式)。例如,它可能会基于 x12 的假设在一个编译单元中优化一个函数,以便该函数在另一个函数中执行语句 *const_cast<int*>(&x) = 13 后永远不会改变其行为.