指向零长度数组的指针的属性

Bat*_*eba 22 c++ language-lawyer

考虑

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}
Run Code Online (Sandbox Code Playgroud)

在复制初始化和删除之间,您是否允许读取指针a + 1

此外,该语言是否允许编译器设置anullptr?

T.C*_*.C. 24

根据最近的 CWG 反射器讨论作为社论问题 3178的结果,new int[0]产生了当前所谓的“过去结束”指针值

因此,a不能为空,并且a + 1[expr.add]/4未定义。

  • _“根据最近 CWG 反射器讨论,由于编辑问题 3178,`new int[0]` 生成当前所谓的“尾后”指针值”_ 这是不准确的。没有太多讨论。有人建议该值应该是“超过对象末尾的指针”,这一说法受到质疑,因为在包含“0”元素的数组中,没有对象可以超过对象的末尾。 (5认同)
  • @Bathsheba 你认为对于有缺陷的措辞还有什么更权威的吗? (2认同)

JaM*_*MiT 5

    auto a = new int[0];
Run Code Online (Sandbox Code Playgroud)

根据[basic.compound.3],存储的值a必须是以下之一:

  1. 指向对象(类型int)的指针
  2. 超过对象末尾的指针
  3. 空值
  4. 无效的

我们可以排除第一种可能性,因为没有int构造类型的对象。第三种可能性被排除,因为 C++ 需要返回一个非空指针(参见[basic.stc.dynamic.allocation.2])。因此,我们有两种可能性:指针越过对象末尾或无效指针。

我倾向于将其a视为一个过去的指针,但我没有一个有信誉的参考来明确地建立这一点。(不过,在[basic.stc] 中有强烈的暗示,看看你如何能得到delete这个指针。)所以我会在这个答案中考虑这两种可能性。

在复制初始化和删除之间,您是否允许读取指针a + 1

该行为是未定义的,如[expr.add.4]所规定的,无论上述哪种可能性适用。

如果a是后尾指针,则认为它指向0没有元素的数组索引处的假设元素。将整数添加ja仅在 时定义0?0+j?n,其中n是数组的大小。在我们的例子中,n是零,所以和a+j定义,只有当j0。特别是,添加1是未定义的。

如果a无效,那么我们完全陷入“否则,行为未定义”。(毫不奇怪,定义的情况仅涵盖有效的指针值。)

此外,该语言是否允许编译器设置anullptr?

否。来自上述[basic.stc.dynamic.allocation.2]“如果请求成功,则可替换分配函数返回的值是非空指针值”。还有一个脚注指出 C++(但不是 C)需要一个非空指针来响应零请求。