wal*_*nut 5 c++ language-lawyer c++17
考虑以下三个程序:
// program 1
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a+1) A;
a[1].b = 1;
}
Run Code Online (Sandbox Code Playgroud)
// program 2
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a) A;
a[0].b = 1;
}
Run Code Online (Sandbox Code Playgroud)
// program 3
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a) A;
a->b = 1;
}
Run Code Online (Sandbox Code Playgroud)
这些程序在 C++17 中有未定义的行为吗?
我看到的问题是,根据[basic.life]/8指针不会自动引用A我通过placement-new 创建的新对象。std::launder需要明确地实现这一点。因此,成员访问将具有未定义的行为,因为它是在其生命周期之外的对象上完成的。
至少对于程序 3 来说,这对我来说似乎很清楚,但是对于程序 1,根据[intro.object]/2,新创建的对象成为数组的子对象,因此应该通过指针算术来访问它,不是吗?
然后程序 2 也不会有未定义的行为,因为指针算法只需要a指向数组的一个元素,不一定在其生命周期内。
原始对象的类型不是 const 限定的,并且如果是类类型,则不包含任何类型为 const 限定的非静态数据成员或引用类型,并且
是唯一使您的成员访问代码行为未定义的子句。
在所有三种情况下,a都是两个对象的数组的名称A,因此成员访问是可以的,因为您正在使用A指针来访问A对象。您没有将 char 缓冲区视为 an A,而是将Aas视为A允许的。