C++20下union布局兼容派生类为活跃成员时访问基类是否为定义行为
class B { void *ptr = nullptr; public: auto get() { return ptr; } }; class D : public B {}; union U { B b; D d; }; void *func() { U u{.d = D{}}; return u.b.get(); // ??? }
行为判定结论
上述代码中标注???的行属于未定义行为,具体判定依据基于C++20标准如下:
- 根据
[class.union.general]章节规则:union的非静态数据成员生命周期开始且未结束时为活跃状态,同一时间union对象最多仅能有一个非静态数据成员处于活跃状态。代码中初始化的是u.d,因此d是当前唯一活跃成员,直接访问非活跃成员u.b本身违反标准要求。 - 你提到的标准布局union公共初始序列例外规则,仅适用于直接读取两个成员公共初始序列的非静态数据成员,此处是调用成员函数,不属于该规则的适用范围,无法得到豁免。
- 指针可互转换规则仅允许通过
reinterpret_cast对满足互转换要求的对象指针做转换后访问,并没有放开union非活跃成员的直接访问限制。哪怕几个对象的地址完全重合,也不能绕过活跃成员规则直接调用非活跃成员的成员函数。 - 目前主流GCC、Clang、MSVC编译器都对这类场景做了兼容扩展,实际运行通常会返回预期的
nullptr,但这属于编译器的额外支持,不属于C++标准规定的合法行为。
内容的提问来源于stack exchange,提问作者Marcel Krüger
相关产品推荐
相关产品推荐

