是称为工会成员的析构函数
Is a Union Member's Destructor Called
c++ 11允许在union
中使用标准布局类型:Member of Union has User-Defined Constructor
我的问题是:我保证自定义析构函数将被调用,当union
超出作用域?
我的理解是切换时必须手动销毁和构造:http://en.cppreference.com/w/cpp/language/union#Explanation
但是像这样的例子呢:
{
union S { string str;
vector<int> vec;
~S() {} } s = { "Hello, world"s };
}
当s
超出作用域时,我是否因为没有调用string
的析构函数而泄漏了在堆上分配的字符串的内存?
在您的示例中,您提供的str
将不会被销毁。[class.union]/2
联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数(10.3)。联合不能有基类。联合不能用作基类。如果联合包含引用类型的非静态数据成员,则程序是病态的。联合中最多只能有一个非静态数据成员具有大括号或相等初始化式。[>注意:如果联合的任何非静态数据成员具有重要的默认构造函数(12.1)、复制构造函数(12.8)、移动构造函数(12.8)、复制赋值操作符(12.8)、移动赋值操作符(12.8)或析构函数(12.4),则联合的相应成员函数必须由用户提供,否则将为联合隐式删除(8.4.3)。- ]
<>共舞,强调我的
由于str
和vec
都有特殊的成员函数,所以你需要自己为联合提供它们。
请注意,根据bogdan下面的注释,空析构函数是不够的。在类。Union]/8我们有
[…如果X是一个联合,它的变体成员是非静态数据成员;[…]
所以这个并集的所有成员都是变体。然后如果我们看[类。我们有
在执行析构函数体并销毁在析构函数体中分配的任何自动对象之后,类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::variant
或boost::variant
您的示例无法编译。默认情况下,联合具有一个已删除的析构函数。当然,应该调用什么析构函数?当然你不能两个都打。并且没有存储任何关于实际构造了哪个成员的信息。提供合适的析构函数取决于您。
下面是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;
^
总是需要用非平凡类型手动调用结构中对象的构造函数。
通常也需要显式地构造它们。这里的赋值工作起来似乎很奇怪。
如果有疑问,您可以在调用析构函数时检查程序集。
这段代码的程序集调用basic_string
构造函数,但不调用析构函数。所以这里会有漏洞。
using namespace std;
int main(int argc, char** argv){
union S { string str;
vector<int> vec;
~S() {} } s = { "Hello, world"s };
}
链接查看程序集:https://godbolt.org/g/wKu3vf
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- C++成员的析构函数顺序与shared_ptr
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 工会成员的析构函数似乎是自动调用的
- 为什么类构造函数为其成员生成析构函数?
- C++类析构函数删除成员(如果"owner"?
- C++ 在析构函数调用之前删除的动态成员数组
- 如何从类成员函数返回指针,例如 size_t * class :: function(); 并使用类析构函数 ~size
- 在这种情况下,工会成员会调用自己的析构函数吗
- 在析构函数之后,围绕成员函数的C++lambda包装器是如何工作的
- C++ 将队列作为成员的类的构造函数和析构函数
- 是否可以访问类数据成员并在析构函数中对它们执行操作?
- 使用 std::function 作为成员函数,它捕获"this",并在析构函数之后从复制的 lam
- 如何在析构函数中执行一些代码*在*成员被销毁之后
- 应该在成员对象上调用析构函数
- 如何为包含map<int,*double>成员的类编写析构函数?
- 为什么在这里调用析构函数,以及在调用该对象析构函数后如何调用对象成员函数?
- 使用线程销毁类析构函数中的shared_ptr成员变量
- C++ 类析构函数删除部分但不是全部成员数据
- C++析构函数是否始终或仅在有时调用数据成员析构函数