考虑以下代码:
#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
是一个分配的内存块时,&data[1]
是否定义,但在data + 1
没有对象或子对象?
如果所讨论的操作符没有重载以表示不同的含义,则x[y]
等效于*(x+y)
。因为+
是可交换的,所以y[x]
也是很有趣的。
在您的示例中,&data[1]
与data+1
完全等价,并且同样定义良好。UB将读取未初始化的内存,取其地址为not。