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]
会引用新对象吗?@walnuta[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;
}