The following program sets the table, eats, and clears the table. The place where the dish goes is cleaned before and after eating. Is that allowed according to the C++23 standard? Or is it undefined behavior? Demo.
class Dish {
// ...
};
class Table {
public:
Table() {
std::memset(&dish, 0, sizeof(dish));
::new (&dish) Dish();
}
~Table() {
dish.~Dish();
std::memset(&dish, 0, sizeof(dish));
}
void Eat() {
dish.Eat();
}
private:
union { Dish dish; };
};
int main() {
Table t;
t.Eat();
}
Because memset writes to an object as if it were a sequence of char values, it does not violate the strict aliasing rule, [basic.lval]/11:
An object of dynamic type
Tobj is type-accessible through a glvalue of typeTref ifTref is similar ([conv.qual]) to:
Tobj,- a type that is the signed or unsigned type corresponding to
Tobj, or- a
char,unsigned char, orstd::bytetype.If a program attempts to access ([defns.access]) the stored value of an object through a glvalue through which it is not type-accessible, the behavior is undefined. If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type
Uwith a glvalue argument that does not denote an object of type cvUwithin its lifetime, the behavior is undefined.
It is not guaranteed that this operation will produce a valid value for the object. But this doesn't matter in your case, because you explicitly construct a Dish object (so its constructor has the responsibility of setting up a valid value, regardless of what was there before.) There is nothing here that would make it UB to perform the memset operation.
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