In your example that you provided str
will not be destructed. The standard states in [class.union]/2
A union can have member functions (including constructors and destructors), but not virtual (10.3) functions. A union shall not have base classes. A union shall not be used as a base class. If a union contains a non-static data member of reference type the program is ill-formed. At most one non-static data member of a union may have a brace-or-equal-initializer . [ Note: If any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]
emphasis mine
So since both str
and vec
have special member functions that are not trivial you will need to provide them for the union yourself.
Do note that as per bogdan's comments below the empty destructor is not enough. In [class.union]/8 we have
[...]If X is a union its variant members are the non-static data members;[...]
So all members of this union are variants. Then if we look at [class.dtor]/8 we have
After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members[...]
So the destructor will not automatically destroy the members of the union as they are variants.
You could make a tagged union like kennytm does here
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();
}
...
};
Which ensures the correct member is destroyed or just use a std::variant
or boost::variant
basic_string
constructor being called but not the destructor: godbolt.org/g/2uvrWn – Foltz{ }
assignment seems like a design flaw of unions because it implicitly allocates but not deallocates. – Foltz