If an array provides storage for an object, does destroying the object
"invalidate" the contents of the array?
void f () {
unsigned char a[1];
using T = unsigned char;
T* p = new (a) T (123);
unsigned char x = a[0];
p->~T ();
unsigned char y = a[0];
assert (x == y);
}
In this case, we have to answer the question of whether the newly created object is an element of the array, or whether the original element is still there and the array is providing storage for the new object.
[intro.object]/2 states that the new object in this particular case is a subobject of the array `a`. Presumably an array cannot have two elements with index 0, so we can infer that the original `a[0]`'s lifetime ends as in
[basic.life]/2.5. The array doesn't provide storage for the new `unsigned char` object. When the new object is later destroyed, `a[0]` is out-of-lifetime and attempting to access its value results in UB.
If you had created an object of some other type, say, `char`, in the storage of `a`, the standard is unclear as to what happens to the value of `a[0]` in that case (either during or after the `char` object's lifetime).
The assert passes using clang (and msvc), but not gcc with optimizations
on. Is gcc doing the "right thing" here? Is this UB? EB?
I'm mostly asking because of how this affects types like vector:
auto f (std::vector<std::unique_ptr<int>>& v) {
auto x = std::move (v.back ());
v.pop_back ();
return x;
}
Here clang bothers to zero out the moved-from unique_ptr, even though it
knows the subsequent destructor is a nop, while gcc doesn't [1].
Obviously (?), gcc's behavior is preferable, but is it correct?
[1] https://godbolt.org/z/b663K1bnd
--
Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion