放置 new &data[i] 而不是 data + i 是 UB 吗?

问题描述

考虑以下代码

#include <string>
struct S { std::string str; };

int main() {
    S *data = static_cast<S*>(operator new(sizeof(S) * 3));
    new (&data[1]) S();  // (1)
    new (data + 2) S();  // (2)
    data[2].~S();  // (3)
    data[1].~S();  // (4)
    operator delete(data);
}

我的理解是第 (2)-(4) 行具有完全有效的行为。

然而,我不确定第 (1) 行:一方面,我从不访问不存在的对象 data[1],因为我只需要它的地址。另一方面,我通过编写 data[1] 来实现,因此可能会调用未定义的行为。

&data[1] 是分配的内存块,但 data 处没有对象或子对象时,是否定义了 data + 1

解决方法

如果所讨论的运算符没有被重载以表示不同的含义,则 x[y] 等价于 *(x+y)。由于 y[x] 是可交换的,因此也有点有趣 +

在您的示例中,&data[1] 完全等同于 data+1 并且同样定义良好。 UB 会读取未初始化的内存,取其地址不是。