【问题标题】:Questions regarding C++ non-POD unions关于 C++ 非 POD 联合的问题
【发布时间】:2013-11-14 20:39:33
【问题描述】:

C++11 让我们可以在联合中使用非 POD 类型,比如我有以下代码;

union
{
    T one;
    V two;
} uny;

在我班级的某个地方,一次只有一个成员会活跃,现在我的问题很简单。

  1. uny 的默认值是多少? - 未定义?
  2. 每当我的类被破坏时,哪些成员(在联合内)将被破坏(如果有的话)?
    • 假设我必须使用 std::typeinfo 来跟踪哪个是活动成员,那么我应该在析构函数中显式调用该成员的析构函数吗?
  3. 是否有人提供语言提案的链接,该提案将工会更改为接受非 POD 类型?

【问题讨论】:

  • This answer 详细介绍了如何实际执行此操作。

标签: c++ c++11 unions discriminated-union


【解决方案1】:

您大部分时间都靠自己。标准中的注释解释了这一点 (9.5/2):

如果联合的任何非静态数据成员具有非平凡的默认值 构造函数 (12.1)、复制构造函数 (12.8)、移动构造函数 (12.8)、复制赋值运算符 (12.8)、移动 赋值运算符(12.8)或析构函数(12.4),联合的相应成员函数必须是 用户提供,否则会为联合隐式删除(8.4.3)。

因此,如果任何成员构造函数是非平凡的,则需要为联合编写一个构造函数(如果它们都是平凡的,则默认状态将是未初始化的,例如union { int; double; })。如果任何成员有析构函数,则需要为联合体编写析构函数,该析构函数必须负责找出活动元素。

还有一个关于无约束联合的典型用法的进一步说明 (9.5/4):

一般来说,必须使用显式的析构函数调用和放置新的操作符来改变活动的 工会成员。

【讨论】:

  • 你能澄清一下什么标准规定的吗? C++11 还是普通的 C++?
【解决方案2】:

联合的替代方案:

std::any / std::variant (C++17)

boost::any/boost::variant

这些允许使用非 POD 数据类型。

【讨论】:

  • 这是一个写得很清楚的(和 3 岁的)问题,询问非 POD 类型的联合的行为。命名一些替代品如何回答这个问题?
  • @ChrisH - 因为替代品可以提供更好的解决方案。它允许将联合的行为与新的现代特性进行比较,这些特性旨在处理非 POD 数据类型。我不明白你关于这个问题已经有 3 年历史的观点了;如果现在可以看到,在 3 或 30 年后,它不应该值得任何更新吗?回复
  • 这篇文章提出了非常具体的问题,即非 POD 类型的联合的行为方式。如果您要说明替代方案的比较方式,那么您将贡献与该问题相关的内容。事实上,您已经回答了“x 如何工作”的问题,“您可以改用y”。这不是客观地回答所提出的问题。即使他们要求替代方案,这也不是一个好的答案。简单地命名替代方案而不比较它们的功能对任何人都没有什么好处。
  • 至于时间问题,我完全同意为老问题添加好的答案是有价值的。但是,当他们对一个完全不同的问题的答案,甚至不是对那个问题的特别好的答案时......这是一个完全不同的故事。
  • 如果您想提供其他您认为相关的信息,尽管不是答案,您可以在评论中这样做。 Stack Overflow 的答案应回答问题
【解决方案3】:

这是一个棘手的问题。

也许你可以用这个:

uny un;
new(&un.one) T;

你可以参考 https://en.cppreference.com/w/cpp/language/union

【讨论】:

    猜你喜欢
    • 2010-12-19
    • 2020-10-13
    • 2022-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多