让所有成员都活跃在C++联盟中安全吗

Is it safe to have all members active in a C++ union?

本文关键字:联盟 C++ 安全 活跃 成员      更新时间:2023-10-16

根据这一点和联合的活动成员并不意味着语言/编译器执行任何操作。我们自己必须确保成员被正确激活/停用,即通过调用它们的构造函数/析构函数。

考虑到这一点,让所有成员都处于活动状态应该是安全的(目前是这样工作的,根本没有进行分配(,但我想知道我是否在某个时候使用了未定义的行为(因为我肯定不会使用placement-new的返回值,为了避免优化器出现问题,必须执行该操作(或std::launder((

/// not really a union 
/// just a handy way to access the individual elements named 
/// and still be able to iterate over them, 
/// thus see bucket and see buckets are always both active
union Buckets
{
using Type = std::map<int,char>;
struct
{
Type    a;
Type    b;
Type    c;
Type    d;
Type    e;
Type    f;
}       bucket;
Type    buckets[6];
static_assert(sizeof(bucket) == sizeof(buckets));
Buckets()  { for (auto& current : buckets) new(&current) Type(); }
~Buckets() { for (auto& current : buckets) current.~Type(); }
};

您不能让所有工会成员都处于"活动"状态。

只有最后一个写入成员的是活动的。

任何从其他成员读取的尝试都会导致未定义的行为。

不可能让联盟的所有成员都处于活动状态(同时(。任何时候只有一个成员处于活动状态。如果激活另一个成员而没有正确地停用前一个成员(如果需要,通过调用析构函数(,则前一个活动成员将被错误地停用,而不是保持活动状态。

如果您希望所有成员都是活动的,那么您需要一个非联合类。

当然,让union的所有成员都处于活动状态是可取的。

请记住,只有写入的最后一个是,因此上面的内容并不那么有趣,因为它只适用于具有零或一个成员的union

https://en.cppreference.com/w/cpp/language/data_members#Standard_layout告诉这么做没问题,至少从C++14 开始

在具有非并集类类型T1的活动成员的标准布局并集中,允许读取非并集类别类型T2的另一并集成员的非静态数据成员m,前提是m是T1和T2的公共初始序列的一部分(通过非易失性glvalue读取易失性成员是未定义的(。

因为在当前情况下,T1和T2无论如何都捐赠相同的类型。