【发布时间】:2020-06-08 00:38:09
【问题描述】:
在 C++ 中,从最近编写的联合成员(即 活动 联合成员)中读取是明确定义的。
我的问题是std::memcpying 整个联合对象,而不是将特定联合成员复制到未初始化的内存区域,是否会保留活动联合成员。
union A {
int x;
char y[4];
};
A a;
a.y[0] = 'U';
a.y[1] = 'B';
a.y[2] = '?';
a.y[3] = '\0';
std::byte buf[sizeof(A)];
std::memcpy(buf, &a, sizeof(A));
A& a2 = *reinterpret_cast<A*>(buf);
std::cout << a2.y << '\n'; // is `A::y` the active member of `a2`?
【问题讨论】:
-
现代 C++ 代码将使用类型安全的
std::variant而不是联合,从而使整个问题变得毫无意义。 -
@SamVarshavchik 即使假设这是真的,我仍然认为这个问题是有效的。
-
常识说它应该只适用于可简单复制类型的联合,但我不完全确定。
-
@SepiaColor 如果没有类型索引,编写类似的东西不会很困难。当然它不能直接复制/移动,但如果你知道里面是什么类型,它仍然可以被分配。
-
由于您使用
undefined-behavior标记,我将指出您应该使用placement new 而不是malloc,因为就语言而言,malloc实际上并不创建对象。您可能还必须在访问权限上输入std::launder才能完全清楚。我不记得在 C++20 中有多少变化,但我知道没有足够的时间来获取 Richard 的全文。(另外,您至少应该能够将*reinterpret_cast<T*>替换为reinterpret_cast<T&>.)
标签: c++ undefined-behavior unions memcpy