2010-03-11 17 views
21

Me gustaría que mi clase tenga un puntero estático a una región de memoria asignada dinámicamente. Entiendo cómo inicializarlo; en mi caso lo inicializaré cuando el primer objeto lo necesite. Sin embargo, no sé cuándo/dónde en el código para liberarlo. Me gustaría liberarlo cuando el programa termine.C++ liberando variables estáticas

Podría liberar el puntero en el destructor de mis objetos, pero luego tendría que mantener un recuento de objetos para ver si es seguro liberarlo cuando el objeto sea el último objeto en uso.

¿Hay una manera más elegante de hacer esto?

Háganme saber.

Gracias, JBU

+0

¿Parece que estás intentando reinventar punteros inteligentes? –

+0

Este problema es uno de los problemas que ocurren al implementar singletons (http://en.wikipedia.org/wiki/Singleton_pattern). El ejemplo del código de @ Klaim a continuación es un ejemplo de uno. Pueden ser una buena cosa o una muleta. No abusar de ellos. :) – Void

Respuesta

18

Tiene dos soluciones aquí:

  1. No elimine eliminarlo (que está en C++, utiliza nuevas y eliminar, haga;?)) . Casi todos los sistemas operativos actuales "liberarán" de todos modos la memoria asignada por la aplicación una vez que haya finalizado. Pero esa no es una buena solución, que hace que las pérdidas de memoria sean difíciles de detectar, por ejemplo.
  2. Encapsule su puntero en una clase (como miembro), luego use esta clase como el tipo de su estática. De esta forma, sabrá que se llamará al destructor de clase al final de la aplicación. A continuación, simplemente borre sus datos en el destructor y el trabajo estará listo y limpio. Ese es el poder de RAII.

Le sugiero que haga 2, esa es una manera muy limpia de hacerlo.


Aquí hay un ejemplo simple. En lugar de hacer esto

static Thing* things = new Thing(); // or whatever way to initialize, here or in a specific function 

que va a hacer lo siguiente:

class ThingManager // or whatever name you like 
{ 
public: 
    ThingManager(Thing* thing) : m_thing(thing) { }//or create it here? whatever solution suits your way of creating the data 

    ~ThingManager() { delete m_thing; } // THAT's the important part! 

    Thing* instance() const { return m_thing; } // or whatever accessor you need, if you need one 

private: 
    Thing* m_thing; 
}; 

y luego

static ManagedThing thing; // now i can access it via thing.instance() 

Cuando termina el programa, será destruido la variable estática (que no se PUNTERO más) y se llamará a su destructor para hacer eso.

Está escrito solo para darle una idea de cómo puede hacerlo.

+0

Lo siento, soy muy nuevo en C++. Cuando dice "se llamará al destructor de clases al final de la aplicación", ¿está diciendo que hay un destructor de objetos y un destructor de clases estático? Además, ¿qué es RAII? – jbu

+0

RAII: http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization Debe conocer las funciones predeterminadas de todas las clases. – Klaim

+4

RAII es un término desafortunado, porque no es muy descriptivo; ver http://en.wikipedia.org/wiki/RAII –

2

Puede declarar su variable estática como un puntero inteligente, y cuando finalice el programa, se liberará el puntero asignado.

0

Yo definiría un contador estático en la clase para el número de pistas instancias de objetos como el destructor llegar ejecutarlo disminuir el contador y si el contador 0 == libre de la memoria también .. tal y como lo

6

Desde el sistema operativo En perspectiva, no hay un punto real en liberar memoria a medida que su programa termina, todo lo que hace es bajar la terminación lentamente. La terminación de su aplicación destruye todo el espacio de direcciones, liberará todo que asigne en el montón de una sola vez. Llamar explícitamente al free al apagar la aplicación es solo arrastrar punteros en el montón que se descartarán de todos modos.

La razón principal por la que tratamos de liberar todo de forma explícita es para asegurarnos de que no estamos perdiendo memoria y nuestra huella de memoria no crece para siempre.

Pero si puede estar seguro de que esto es estático, que solo habrá uno, y que no puede liberarlo de forma segura hasta que todos sus otros objetos hayan sido liberados, este es un caso en el que podría ser mejor solo para que la finalización de la aplicación se encargue de ello.

+0

Gracias por la respuesta. Siempre pensé que las pérdidas de memoria harían que el sistema operativo se aferrara a la memoria reservada/no actualizada incluso después de la finalización del programa. – jbu

+1

@jbu: No sería un muy buen sistema operativo si hiciera eso. ;) –

+2

Aunque ocultará otras fugas de memoria con algunas herramientas de detección de fuga de memoria, por lo que no se recomienda de todos modos. – Klaim

14

Tíralo con un puntero inteligente. Tendrá duración estática y ser destruido después de main rendimientos:

static std::auto_ptr<T> thePointer; 

Otra opción es registrar su propia atexit función:

// static 
void YourClass::freePointer(void) 
{ 
    delete getPointer(); 
} 

// static 
T* YourClass::getPointer(void) 
{ 
    if (!thePointer) 
    { 
     thePointer = new T; 
     atexit(freePointer); 
    } 

    return thePointer; 
} 

que tendrá el mismo efecto. Otra opción que ya mencionas es mantener un contador estático. Tenga en cuenta que en realidad puede concluir con bastante eficacia.

+1

Alexandrescu usa 'atexit' en la implementación de su' Loki :: Singleton'.De esta forma, se asegura de que los métodos que liberan al puntero también restablezcan su estado a '0' para que puedan ser reasignados si es necesario (caso de la política de vida útil de' Phoenix'). Personalmente creo que un 'auto_ptr' o incluso mejor' unique_ptr' significa mucho menos problemas. –

+0

Esto no es bueno, solo hay un pequeño número limitado de funciones de limpieza at_exit, a veces tan bajas como 32 (el mínimo definido en el estándar) – Lothar