以下程序负责摆桌子、吃饭和清理桌子。吃饭前和吃饭后,盘子所在的地方都会被清理干净。根据 C++23 标准允许这样做吗?或者这是未定义的行为? 演示。
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();
}
因为
memset
写入对象就好像它是 char
值的序列,所以它不违反严格的别名规则,[basic.lval]/11:
动态类型
obj 的对象可以通过T
T
ref类型的泛左值实现类型可访问,如果ref 类似于 ([conv.qual]) :T
obj, 与T
obj 对应的有符号或无符号类型,或者T
、char
或unsigned char
类型。std::byte
如果程序尝试通过不可类型访问的泛左值来访问([defns.access])对象的存储值,则行为是未定义的。如果程序为
类型的联合调用默认的复制/移动构造函数或复制/移动赋值运算符,其泛左值参数在其生命周期内不表示 cvU
类型的对象,则行为未定义.U
不保证此操作将为对象生成有效值。但这在你的情况下并不重要,因为你显式构造了一个
Dish
对象(因此它的构造函数有责任设置一个有效值,无论之前有什么。)这里没有什么可以让它成为 UB执行 memset
操作。