问题 有关C ++非POD联合的问题


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

union
{
    T one;
    V two;
} uny;

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

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

13021
2017-11-04 08:42


起源



答案:


你主要靠自己。标准中的注释解释了这一点(9.5 / 2):

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

因此,如果任何成员构造函数都是非平凡的,那么您需要为union编写一个构造函数(如果它们都是微不足道的,那么默认状态将是未初始化的,例如 union { int; double; })。如果任何成员都有析构函数,则需要为union编写析构函数,该析构函数必须处理活动元素。

关于无约束联合的典型用法,还有一个注释(9.5 / 4):

通常,必须使用显式析构函数调用和放置新运算符来更改活动   工会成员。


13
2017-11-04 09:10



你可以澄清一下标准指定的内容吗? C ++ 11还是普通的C ++? - Pavel
@Pavel:C ++ 11,其中 是 此时常规的C ++。 - Kerrek SB


答案:


你主要靠自己。标准中的注释解释了这一点(9.5 / 2):

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

因此,如果任何成员构造函数都是非平凡的,那么您需要为union编写一个构造函数(如果它们都是微不足道的,那么默认状态将是未初始化的,例如 union { int; double; })。如果任何成员都有析构函数,则需要为union编写析构函数,该析构函数必须处理活动元素。

关于无约束联合的典型用法,还有一个注释(9.5 / 4):

通常,必须使用显式析构函数调用和放置新运算符来更改活动   工会成员。


13
2017-11-04 09:10



你可以澄清一下标准指定的内容吗? C ++ 11还是普通的C ++? - Pavel
@Pavel:C ++ 11,其中 是 此时常规的C ++。 - Kerrek SB


联盟的替代方案:

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

boost::any / boost::variant

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


0
2017-10-11 11:13



这是一个非常清晰(3年前)的问题,询问有非POD类型的工会的行为。如何命名一些替代方案来回答这个问题? - Chris H
@ChrisH - 因为替代品可以提供更好的解决方案。它允许将工会的行为与旨在处理非POD数据类型的新现代功能进行比较。我不明白你的观点是这个问题是3岁;如果现在可以看到,在3或30年的时间内,是否值得任何更新?敬请回复 - Pietro
该帖子询问关于非POD类型的联合如何表现的非常具体的问题。如果您要说明替代方案的比较方式,那么您将提供与该问题相关的内容。事实上,你已经回答了“怎么做 x 你可以使用的工作“问题” y “这是客观上没有回答所提出的问题。即使他们要求替代方案,这也不是一个好的答案。简单地命名替代品而不比较他们的功能对任何人都没什么好处。 - Chris H
至于计时问题,我完全同意补充 好 旧问题的答案很有价值。但是,当他们回答一个完全不同于问题的问题时,甚至对那个问题的答案都不是特别好......这是一个完全不同的故事。 - Chris H
如果您想提供您认为相关的其他信息,尽管不是答案,您可以在评论中这样做。预计Stack Overflow答案 回答问题。 - Chris H