sintaxis palabras conjuntos c++ c++11 destructor unions standard-layout

c++ - palabras - Se llama destructor de un miembro de la Unión



union de palabras en c++ (3)

En tu ejemplo que proporcionaste, str no será destruido. Los estados estándar en [class.union] / 2

Una unión puede tener funciones miembro (incluidos constructores y destructores), pero no funciones virtuales (10.3). Un sindicato no tendrá clases de base. Una unión no debe ser usada como una clase base. Si una unión contiene un miembro de datos no estáticos de tipo de referencia, el programa está mal formado. A lo sumo, un miembro de datos no estáticos de una unión puede tener un inicializador de refuerzo o igual. [ Nota: Si algún miembro de datos no estáticos de una unión tiene un constructor predeterminado no trivial (12.1), copia constructor (12.8), mueva constructor (12.8), copie el operador de asignación (12.8), mueva asignación operador (12.8), o destructor (12.4), la función miembro correspondiente de la unión debe ser proporcionada por el usuario o se eliminará implícitamente (8.4.3) para la unión. - nota final ]

énfasis mio

Por lo tanto, como str y vec tienen funciones de miembro especiales que no son triviales, deberá proporcionarlas usted mismo para la unión.

Tenga en cuenta que según bogdan''s comentarios bogdan''s debajo del destructor vacío no es suficiente. En [class.union] / 8 tenemos

[...] Si X es una unión, sus miembros variantes son los miembros de datos no estáticos;

Así que todos los miembros de esta unión son variantes. Entonces si miramos [class.dtor] / 8 tenemos

Después de ejecutar el cuerpo del destructor y destruir cualquier objeto automático asignado dentro del cuerpo, un destructor para la clase X llama a los destructores para los miembros de datos no estáticos directos no variables de X [...]

Por lo tanto, el destructor no destruirá automáticamente a los miembros de la unión ya que son variantes.

Usted podría hacer una unión etiquetada como kennytm hace 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(); } ... };

Lo que garantiza que el miembro correcto se destruya o simplemente use std::variant o boost::variant

C ++ 11 permitió el uso de tipos de diseño estándar en una union : El miembro de Union tiene un constructor definido por el usuario

Entonces mi pregunta es: ¿tengo la garantía de que se llamará al destructor personalizado cuando el union se salga de su alcance?

Mi entendimiento es que debemos destruir y construir manualmente al cambiar: http://en.cppreference.com/w/cpp/language/union#Explanation

Pero ¿qué pasa con un ejemplo como este:

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

Cuando s queda fuera del alcance, ¿he filtrado a la memoria la cadena asignada en el montón porque no llamé al destructor de la string ?


Siempre debe llamar manualmente al constructor de los objetos en su estructura con tipos no triviales.

Por lo general, siempre hay que construirlos explícitamente también. Parece extraño que la tarea aquí funcione.

En caso de duda, siempre se puede verificar el ensamblaje si se llama a los destructores.

El ensamblaje de este código llama al constructor basic_string pero no al destructor. Así que tendrás fugas aquí.

using namespace std; int main(int argc, char** argv){ union S { string str; vector<int> vec; ~S() {} } s = { "Hello, world"s }; }

enlace para ver el ensamblaje: https://godbolt.org/g/wKu3vf


Tu ejemplo no compilará. Los sindicatos tienen, por defecto, un destructor eliminado. Porque por supuesto, ¿qué destructor debería llamarse? Seguro que no puedes llamar a los dos. Y en ninguna parte se almacena información sobre qué miembro se construyó realmente. Depende de usted para proporcionar un destructor adecuado.

Aquí está la salida de GCC al intentar compilar su fragmento de código:

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; ^