2010-01-04 10 views
12

Tengo un std::queue que se ajusta como una clase de plantilla para hacer una cola segura para subprocesos. Tengo dos versiones de esta clase: una que almacena tipos de valores, una que almacena tipos de punteros.C++ std :: queue :: pop() llama a destructor. ¿Qué hay de los tipos de punteros?

Para el tipo de puntero, tengo problemas para eliminar los elementos de la cola en la destrucción. La razón es que no sé cómo eliminar los elementos de la cola de forma segura.

This estados de referencia (de forma vaga, así que supongo que en realidad NO LO DECLARAN) que la única manera de eliminar elementos de la cola es llamar al pop(). La referencia también dice que pop() llama al destructor para el artículo.

Bueno, esto causa problemas con mis tipos de punteros porque pueden o no señalar agregados. Si uno de ellos apunta a un agregado, todos lo harán, pero debido a que el contenedor está modelado, no hay garantía de qué tipo (agregado o no agregado) estamos tratando.

Entonces, cuando pop() llama al destructor, ¿qué ocurre? ¿Cómo me aseguro de que todo se elimine y la asignación de memoria sea correcta?

Por último, mi solución está utilizando una versión anterior de GCC para ARM9. No tengo control sobre esto. Entiendo que hay bibliotecas que tienen punteros inteligentes y contenedores que ayudarían aquí, pero están fuera de mi alcance.

+0

"Bueno, esto causa problemas con mis tipos de punteros porque pueden o no señalar agregados" No entiendo qué agregados tienen que ver con nada aquí. –

Respuesta

13

Las fuentes en línea valen lo que pagas por ellas; obtén una referencia adecuada como Josuttis's book. pop() no "llama al destructor": simplemente elimina un elemento de la representación subyacente del adaptador de cola (de forma predeterminada, std :: deque) al invocar pop_front() en él. Si el elemento que se muestra tiene un destructor, se usará cuando el objeto reventado quede fuera del alcance, pero la clase de cola no tiene nada que ver con él.

+0

Thx para aclarar, tuve problemas para entender esa afirmación: "Esto llama al destructor del elemento eliminado" –

+0

suponiendo que el objeto reventado se ha insertado en un puntero inteligente de alguna forma. –

+0

Gracias por la información y el enlace del libro. –

30

Punteros a sí mismos en realidad no tienen destructores, así que llamar pop() en una cola que contiene un puntero no llamará al destructor del objeto de sus puntos de puntero a.

+0

Gracias por la respuesta.Esto es lo que me preguntaba, si no estaba claro por mi pregunta. –

+0

Greg, agradezco la respuesta rápida y todavía voto, pero cambié mi aceptación a la respuesta de Neil porque tiene una explicación más minuciosa de lo que está sucediendo. –

+0

Estoy de acuerdo. Aunque la línea de pensamiento es muy buena: D. El primer signo revelador debe ser que un puntero no tiene un destructor. –

1

"¿Cómo me aseguro de que se elimine todo y de que la memoria se desasigne correctamente?"

Si tiene que almacenar punteros en su cola, y desea que se liberen automáticamente cuando están pop ed, en lugar de una cola de punteros, necesita una cola de objetos que almacenan un puntero, y eliminarlo en su destructor. Por ejemplo, podría usar una cola de shared_ptr. shared_ptr no está en la biblioteca estándar, pero es parte de TR1 y está ampliamente disponible.

lo contrario, es la responsabilidad de la persona que llama para eliminar el objeto:

T *off = q.front(); 
q.pop(); 
delete off; 

El resumen es que los contenedores de punteros a objetos asignados dinámicamente son un poco incómodo. Si puede diseñar su programa para que los contenedores almacenen copias de sus objetos, en lugar de punteros a objetos dinámicos, hágalo. De lo contrario, usted es responsable de la propiedad del recurso, no del contenedor. Los contenedores STL no saben nada sobre la propiedad, solo copian y destruyen su value_type. Copiar y destruir punteros no hace nada con los objetos a los que apuntan.

+0

Pensé en esto, pero lo rechacé porque no sé los usos futuros de la clase con plantilla. No quiero darles acceso sin procesar a la cola para los usuarios por cuestiones de seguridad de subprocesos, y no puedo garantizar que los usuarios utilicen la idea que acabas de mencionar, así que decidí no hacerlo. –

+0

Si su clase está utilizando su parámetro de plantilla como el tipo de valor para una cola oculta, probablemente debería hacer lo que hacen los contenedores: si el usuario asigna algo, entonces el usuario tiene que organizarlo para eventualmente liberarlo (por ejemplo, usando un smart puntero como tipo de valor). Por ejemplo, si se trata de una cola de eventos, y el usuario insiste en usar un puntero simple, entonces tal vez podría liberar el objeto en el controlador de eventos. Pero no es el problema del contenedor, y la OMI no debe intentar escribir contenedores que traten especialmente los punteros. –

+0

... admitidamente, esto solo lleva el problema al siguiente tipo. Pero hay buenas razones para no confundir los contenedores con la propiedad, uno de los cuales es que alguien quiera usar su contenedor para almacenar punteros, sin darle propiedad (porque apuntan a datos estáticos o algo así). Supongo que boost :: ptr_deque se puede utilizar como el contenedor subyacente de una cola, por lo que podría tener dos parámetros de plantilla (como la cola) y dejar que el usuario lo use si hace lo que quiere. –

Cuestiones relacionadas