2012-05-11 18 views
10

Aquí, por "simple", me refiero a una clase con destructor vacío no virtual o tipo POD.¿Necesitamos llamar explícitamente al destructor para las "clases de POD simples" asignadas con "colocación nueva"?

ejemplo típico:

char buffer[SIZE]; 
T *p = new(buffer) T; 
... 
p->~T(); // <---- always ? 

¿Qué pasa si no lo llamamos el destructor explícito sobre p? No creo que sea un comportamiento indefinido o una fuga de memoria.
¿Hay algún problema con la reutilización buffer?

+0

@EdChum ¿Por qué? Él está colocando un solo objeto encima de ese buffer. – Benj

+0

@Benj lo siento acaba de darse cuenta de mi error – EdChum

+1

Con la colocación nueva, ¿también es responsable de llamar al destructor de cualquier subtipo? – Benj

Respuesta

9

Para un POD-type o una clase con un trivial destructor: no. La vida útil del objeto finalizará cuando se libere o reutilice el almacenamiento del objeto. No tiene que llamar al destructor explícitamente si no lo desea.

Dicho esto, no hay ninguna razón para no hacerlo. Para un tipo con un destructor trivial, la llamada al destructor no generará ningún código.

Si, por una clase con un destructor "vacío" está permitiendo la posibilidad de que la clase tenga miembros o clases base con destructores no triviales, puede obtener un comportamiento indefinido si su programa depende de la invocación de estos destructores.

Tenga en cuenta que un destructor proporcionado por el usuario es un destructor no trivial, incluso si no es virtual y está vacío. A pesar de esto, todavía se le permite finalizar la vida útil de un objeto con dicho destructor simplemente liberando o reutilizando su almacenamiento, siempre que su programa no dependa de los efectos secundarios del destructor. (Consulte 3.8 [basic.life]/4 de ISO/IEC 14882: 2011)

+0

"_puede obtener un comportamiento indefinido si su programa se basa en la invocación de estos destructores._" esta afirmación no tiene sentido. Obtienes un comportamiento definido, el comportamiento de tu código. – curiousguy

+1

@curiousguy: si el código tiene un comportamiento definido, entonces, por definición, no puede confiar en que se invoquen tales destructores. No estoy seguro de que esta parte del estándar diga mucho más que circularmente dar una pista sobre la definición de "confiar", pero no creo que sea inconsistente. –

+0

"_No creo que sea inconsistente_" No. Es solo tautológico. También podría decirse que el código que espera 'cout <<" ";' para imprimir 'Hello, World' no está definido ... el estándar tiene muchas declaraciones absurdas, y esta es una de mis favoritas. – curiousguy

12

Técnicamente hablando, suponiendo que el destructor no libera ningún recurso adquirido durante la construcción, puede que no sea necesario.

Sin embargo, considerando los aspectos no técnicos (mantenimiento y evolución del código), me apegaría a las mejores prácticas: lo que se construyó, se debe destruir. Escenario a considerar: ¿y si en el futuro algunos cambios determinarán el código relevante que se colocará en el destructor? ¿Te acordarás de que detestas la destrucción de ese tipo de objeto?

+2

¡Tomaré el sentido común sobre una cita estándar tonta cualquier día! – Pubby

+1

Me gusta la parte 'me apegaré a la mejor práctica '. –

1

Si su clase maneja algunos recursos (memoria del montón, identificadores, contadores, mutexes ...) o contiene algunos campos que manejan recursos, estos recursos no se liberarán si no llama al destructor explícitamente. De lo contrario, no hay ningún problema con la destrucción. Puede considerar la clase no destruida como basura en la memoria y construir una nueva libremente en el mismo lugar.

+0

Habla de tipos de POD ... ¿por qué tendría un mutex, contador, etc.? – celavek

+0

POD puede contener un puntero o identificador para mutex que se puede adquirir durante la construcción/vida útil del objeto – inkooboo

+3

@inkooboo: un POD puede contener un puntero pero solo puede contener un identificador si el tipo de identificador también es POD. El mutex no se puede adquirir durante la construcción de un objeto POD ya que implicaría que el POD tenía un constructor no trivial. –

0

Sí, debe llamar al destructor explícitamente (tenga en cuenta los efectos secundarios de T, es decir, libere algo de memoria adicional). Además, debe tener cuidado con la alineación de la memoria cuando usa la ubicación nueva.

Si lo desea, puede reutilizar la memoria intermedia.

tenga en cuanta también http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14

+0

No es realmente la pregunta, el OP pregunta específicamente sobre POD – Benj

Cuestiones relacionadas