通过常量指针修改使用 new 创建的对象是否合法

Is it legal to modify an object created with new through a const pointer?

本文关键字:创建 对象 是否 new 常量 指针 修改      更新时间:2023-10-16

所以这个答案让我想到了将new的结果分配给指向const的指针的场景。AFAIK,在这种情况下,您没有理由不能合法const_cast恒常性并实际修改对象:

struct X{int x;};
//....
const X* x = new X;
const_cast<X*>(x)->x = 0; // okay

但后来我想 - 如果你真的想new创建一个const对象怎么办。所以我尝试了

struct X{};
//....
const X* x = new const X;

它编译了!!

这是 GCC 扩展还是标准行为?我在实践中从未见过这种情况。如果它是标准的,我会尽可能开始使用它。

new显然不会创建一个 const 对象(我希望)。

如果要求new创建const对象,则会得到一个const对象。

您没有理由不能合法地const_cast恒常性并实际修改对象。

有。原因是语言规范明确地将其称为未定义的行为。所以,在某种程度上,你可以,但这几乎没有任何意义。

我不知道你对此有什么期望,但如果你认为问题是在只读内存中分配与否,那就远非重点了。没关系。编译器可以假设这样的对象无法相应地更改和优化,并且最终会得到意想不到的结果。

const

该类型的一部分。无论您是否分配具有动态、静态或自动存储持续时间的对象,都无关紧要。它仍然const.抛弃这种const性并改变对象仍然是一个未定义的操作。

const ness是类型系统赋予我们围绕不可变对象实现安全性的抽象;它这样做在很大程度上是为了帮助我们与只读内存进行交互,但这并不意味着它的语义仅限于这种内存。事实上,C++甚至不知道什么是只读内存,什么不是只读内存。

除了可以从所有常用规则派生出来之外,对于动态分配的对象没有例外[lol],标准明确提到了这一点(尽管在注释中):

[C++03: 5.3.4/1]: new-expression 尝试创建应用该表达式的类型 id (8.1) 或新类型 ID 的对象。该对象的类型是分配的类型。此类型应是完整的对象类型,但不是抽象类类型或其数组(1.8,3.9,10.4)。[注意:由于引用不是对象,因此不能由新表达式创建引用。] [注意:类型ID可以是cv限定的类型,在这种情况下,new-expression创建的对象具有cv限定的类型。

[C++11: 5.3.4/1]: new-expression 尝试创建应用它的类型 id (8.1) 或新类型 id 的对象。该对象的类型是分配的类型。此类型应是完整的对象类型,但不是抽象类类型或其数组(1.8,3.9,10.4)。是否支持过度对齐的类型由实现定义 (3.11)。[ 注意:由于引用不是对象,因此不能由新表达式创建引用。—尾注 ] [ 注意:类型ID可以是CV限定的类型,在这种情况下,新表达式创建的对象具有CV限定类型

[C++11: 7.1.6.1/4]中还给出了一个使用示例。

不知道你还期待什么。我不能说我自己曾经这样做过,但我看不出有什么特别的理由不这样做。可能有一些技术社会学家可以告诉你统计数据,我们很少动态分配某些东西,只是将其视为不可变的。

我看待这个问题的方式是:

  • Xconst X以及指向它们的指针是不同的类型
  • 有一个从X*const X*的隐式转换,但不是相反
  • 因此,以下内容是合法的,每种情况下x具有相同的类型和行为

    常量 X* x = 新 X;常量 X* x = 新的常量 X;

剩下的唯一问题是,在第二种情况下(可能在只读内存中)是否可以调用不同的分配器。答案是否定的,标准中没有这样的规定。