2012-07-26 17 views
5

Actualmente estoy entrando en C++ para la codificación de nivel inferior con OpenGL. Vengo de un entorno obsoleto pesado, así que tengo un poco de conocimiento sobre la administración de la memoria, pero parece que no puedo ver cómo la biblioteca "boost" maneja tipos de contenedores como ptr_vector.¿Cómo gestiona ptr_vector la memoria?

Creo que mi problema está relacionado con el hecho de que no tengo idea de cómo ptr_vector logra la destrucción de sí mismo y sus objetos.

favor, eche un vistazo al código siguiente:

// Header file 
... 
ptr_vector<IObject3D> objects; 
... 

// Implementation file 
... 
void ApplicationEngine::init() 
{ 
    WavefrontObject3D *object = new WavefrontObject3D("Ninja.obj"); 
    objects.push_back(object); 
} 
... 

Por lo tanto, para la realidad cuestionar: estoy creando una fuga aquí a través del "objeto" variable?

Estoy acostumbrado a retener y liberar mis objetos manualmente con llamadas explícitas en objc: Anteriormente había alloc init a la WavefrontObject3D object, agregarlo a una matriz y después release ese mismo objeto de evitar fugas.

Pero cuando agrego un delete object después de la llamada push_back se llama al deconstructor del WavefrontObject3D object. Esto me da una pista de que el ptr_vector no conserva la variable object. ¿Mi suposición es correcta?

adicional, pero relacionado, pregunta: digamos que quieren destruir la clase que contiene ApplicationEngine no tengo que llamar a algún tipo de Deconstructor en el ptr_vector o los elementos que administra?

+0

'Pero cuando agrego un objeto delete después de la llamada push_back, se llama al deconstructor del objeto WavefrontObject3D. Bueno, eso es para lo que' delete' está hecho. Llama al destructor en la instancia a la que apunta el puntero. – Nobody

+1

Creo que debería leer en [RAII] (http://stackoverflow.com/q/395123/20984), que es la forma en que la mayoría de la administración de memoria se realiza en el llamado "moderno" C++. –

+0

Gran recurso @LucTouraille! Exactamente de la forma en que quería acercarme a C++. – polyclick

Respuesta

5

No, esto no crea una fuga. Todos los contenedores ptr_* eliminarán los objetos que estén almacenados en ellos cuando el contenedor se salga del alcance.

Si elimina el objeto después de agregarlo al contenedor, creará undefined behavior ya que el contenedor intentará eliminarlo de nuevo.

Pregunta adicional: No, si almacena el ptr_vector por valor, su duración está gestionada por el alcance de la clase circundante.

Escribamos una implementación simple de ptr_vector. No tiene soporte para iteradores indirectos y eliminadores personalizados y muchas otras cosas, pero muestra los principios utilizados.

template <typename T> 
class ptr_vector { 
public: 
    // assume control over it 
    void push_back(T* x) 
    { if(x) c_.push_back(x); else throw bad_pointer(); } 

    ~ptr_vector() { 
    // delete everything that is stored here 
    for(auto x : c_) delete x; 
    } 
private: 
    std::vector<T*> c_; 
}; 


// a user class 
struct user_class { 
    void addSomething() { x.push_back(new int(23)); } 
    ptr_vector<int> x; 
}; 

clase de usuario Si se sale del ámbito, el destructor de ptr_vector se ser llamados y se recuperará toda la memoria. Sin fugas a la vista.

+0

+1 para mostrar el funcionamiento interno de 'ptr_vector';) – polyclick

0

ptr_vector liberará todos los elementos en su destructor, por lo que no tiene que hacer nada más que lo que ya hace, es decir, crear los objetos, agregarlos al ptr_vector, y dejar la administración a él. Llamar al delete explícitamente hará que el objeto se destruya dos veces (una cuando lo solicite y otra vez cuando termine el ptr_vector). En otras palabras, ptr_vector no duplica el objeto.

Cuando finaliza el ApplicationEngine, si tiene una instancia del ptr_vector, se llamará al destructor de ese vector, que a su vez eliminará los objetos agregados.

2
void push_back(T* x); 

Requisitos: x = 0 Efectos: inserta el puntero en el recipiente y toma posesión de ella Lanza: bad_pointer si x == 0 seguridad Excepción: fuerte garantía

template 
    < 
     class T, 
     class CloneAllocator = heap_clone_allocator, 
     class Allocator  = std::allocator<void*> 
    > 
    class ptr_vector : public ptr_sequence_adapter 
           < 
            T, 
            std::vector<void*,Allocator>, 
            CloneAllocator 
           > 

Para que pueda especificar su propio CloneAllocator y no eliminar los elementos almacenados en ptr_vector, pero heap_clone_allocator (par predeterminado para CloneAllocator) elimina todos los elementos almacenados en destructor.

http://www.boost.org/doc/libs/1_50_0/libs/ptr_container/doc/reference.html#class-heap-clone-allocator

Cuestiones relacionadas