问题描述
考虑以下代码:
#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 会读取未初始化的内存,取其地址不是。