C++ 数组元素和指针值上的新位置

C++ 数组元素和指针值上的新位置,c++,c++17,language-lawyer,C++,C++17,Language Lawyer,考虑以下三个计划: // 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; } //程序1 #包括 结构A{ 常数INTA=0; int b=0; }; int main(){ 自动a=新a[2]; 新(a+1)a; a[1].b=1; } /

考虑以下三个计划:

// 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;
}
//程序1
#包括
结构A{
常数INTA=0;
int b=0;
};
int main(){
自动a=新a[2];
新(a+1)a;
a[1].b=1;
}
//程序2
#包括
结构A{
常数INTA=0;
int b=0;
};
int main(){
自动a=新a[2];
新的(a)a;
a[0].b=1;
}
//程序3
#包括
结构A{
常数INTA=0;
int b=0;
};
int main(){
自动a=新a[2];
新的(a)a;
a->b=1;
}
这些程序在C++17中是否有未定义的行为

我看到的问题是,根据指针,指针不会自动引用我通过新放置创建的新
A
对象<代码>标准::流槽是实现这一目标的明确要求。因此,成员访问将具有未定义的行为,因为它在对象的生命周期之外对对象进行访问

至少对程序3来说,这似乎很清楚,但对程序1来说,根据新创建的对象成为数组的子对象,因此应该通过指针算法来访问它,不是吗

程序2也不会有未定义的行为,因为指针算法只需要
a
来指向数组的一个元素,而不一定是在它的生命周期内

原始对象的类型不是常量限定的,如果是类类型,则不包含任何类型为常量限定的非静态数据成员或引用类型,以及

是使成员访问代码行为未定义的唯一子句


在所有三种情况下,
a
是两个
a
对象数组的名称,因此成员访问是可以的,因为您使用
a
指针访问
a
对象。您没有将字符缓冲区视为
a
,而是将
a
视为和
a
,这是允许的。

@walnut对的,它是8.3,这就是原因。如果8.3不存在,那么我断言所有代码都是合法的。啊,好吧,我误解了你的答案。但是为什么
a[1]
没有引用程序1中的新对象呢?它似乎是一个子对象,因此是数组的元素,所以通过它可以到达?你认为
std::launder(a)[1]
会引用新对象吗?@walnut
a[1]
*(a+1)
<代码>(a+1)是指向原始对象的指针。但由于8.3的原因,您不能使用该指针。我不确定是否可以使用launder来破坏此规则。因此,在您的解释中,新对象永远不会成为数组的“元素”,或者至少指针算法将始终生成指向原始对象的指针。
// 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;
}
// 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;
}