工会成员的析构函数是否被调用

新手上路,请多包涵

C++11 允许在 union 中使用标准布局类型: 联盟成员具有用户定义的构造函数

然后我的问题是:当 union 超出范围时,我是否保证会调用自定义析构函数?

我的理解是切换时必须手动销毁和构造:http: //en.cppreference.com/w/cpp/language/union#Explanation

但是像这样的例子呢:

 {
    union S { string str;
              vector<int> vec;
              ~S() {} } s = { "Hello, world"s };
}

s 超出范围时,我是否因为没有调用 string 的析构函数而泄漏了在堆上分配的字符串的内存?

原文由 Jonathan Mee 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 391
2 个回答

在您提供的示例中 str 不会被破坏。 [class.union]/2 中的标准状态

联合可以具有成员函数(包括构造函数和析构函数),但不能具有虚拟 (10.3) 函数。联合不应有基类。联合不应用作基类。如果联合包含引用类型的非静态数据成员,则程序格式错误。最多一个联合的非静态数据成员可以有一个大括号或相等初始化器。 [ 注意:如果联合的任何非静态数据成员具有非平凡的默认构造函数 (12.1)、复制构造函数 (12.8)、移动构造函数 (12.8)、复制赋值运算符 (12.8)、移动赋值运算符 (12.8),或析构函数(12.4),联合的相应成员函数必须是用户提供的,否则它将为联合隐式删除(8.4.3)。 ——尾注]

强调我的

因此,由于 strvec 都具有重要的特殊成员函数,因此您需要自己为联合提供它们。

请注意,根据 bogdan 在空析构函数下方的 评论是不够的。在 [class.union]/8 我们有

[…]如果 X 是一个联合,它的变体成员是非静态数据成员;[…]

所以这个联盟的所有成员都是变种。然后,如果我们查看 [class.dtor]/8 我们有

在执行析构函数的主体并销毁主体内分配的任何自动对象后,类 X 的析构函数调用 X 的直接非变体非静态数据成员的析构函数[…]

所以析构函数不会自动销毁联合的成员,因为它们是变体。

你可以像 kennytm这里 做一个带 标签的联合

struct TU {
   int type;
   union {
     int i;
     float f;
     std::string s;
   } u;

   TU(const TU& tu) : type(tu.type) {
     switch (tu.type) {
       case TU_STRING: new(&u.s)(tu.u.s); break;
       case TU_INT:    u.i = tu.u.i;      break;
       case TU_FLOAT:  u.f = tu.u.f;      break;
     }
   }
   ~TU() {
     if (tu.type == TU_STRING)
       u.s.~string();
   }
   ...
};

这确保正确的成员被破坏或只使用 std::variantboost::variant

原文由 NathanOliver 发布,翻译遵循 CC BY-SA 3.0 许可协议

您的示例无法编译。默认情况下,联合有一个已删除的析构函数。因为当然,应该调用什么析构函数?当然,你不能同时调用两者。并且任何地方都没有存储有关实际构造哪个成员的任何信息。提供适当的析构函数取决于您。

这是尝试编译代码片段时 GCC 的输出:

 In function ‘int main()’:
error: use of deleted function ‘main()::<anonymous union>::~<constructor>()’
       vector<int> vec; } s = { "Hello, world"s };
                                                ^

note: ‘main()::<anonymous union>::~<constructor>()’ is implicitly deleted because the default definition would be ill-formed:
      union { string str;
            ^

原文由 G. Sliepen 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题