Consider the following three programs:
// 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;
}
// 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;
}
Do these programs have undefined behavior in C++17?
The problem I see is that according to [basic.life]/8 pointers will not automatically refer to the new A
objects that I am creating via placement-new. std::launder
is required explicitly to achieve that. Thus the member access will have undefined behavior as it is done on an object outside its lifetime.
At least for program 3 this seems clear to me, but for program 1, according to [intro.object]/2 the newly created object becomes a subobject of the array and so it should be reached via pointer arithmetic, shouldn't it?
And program 2 would then also not have undefined behavior, because the pointer arithmetic only requires a
to point to an element of the array, not necessarily in its lifetime.
I believe that [basic.life]/8.3
the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
Is the only clause that makes your member access code undefined behavior.
In all three cases a
is the name of an array of two A
objects so the member access is okay because you are using an A
pointer to access an A
object. You're not treating a char buffer as an A
, you treating an A
as and A
which is allowed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With