web-dev-qa-db-fra.com

C++ libérant des variables statiques

J'aimerais que ma classe ait un pointeur statique sur une région mémoire allouée dynamiquement. Je comprends comment l’initialiser - dans mon cas, je l’initialisera lorsque le premier objet en aura besoin. Cependant, je ne sais pas quand/où dans le code pour le libérer. Je voudrais le libérer quand le programme se termine.

Je pourrais peut-être libérer le pointeur dans le destructeur de mes objets, mais je devrais alors conserver un compte d'objets pour voir s'il était libre de le libérer lorsque l'objet était le dernier objet utilisé. 

Y a-t-il une manière plus élégante de faire ceci? 

S'il vous plaît, faites-moi savoir.

Merci, Jbu

22
jbu

Vous avez deux solutions ici:

  1. Ne pas supprimer, supprimez-le (vous êtes en C++, vous utilisez new et delete, non?;)). Presque tous les systèmes d’exploitation actuels «libéreront» la mémoire allouée par l’application une fois celle-ci terminée. Mais ce n'est pas une bonne solution, cela rend les fuites de mémoire difficiles à détecter, par exemple.
  2. Encapsulez votre pointeur dans une classe (en tant que membre) , puis utilisez cette classe comme type de votre statique. De cette façon, vous savez que le destructeur de classe sera appelé à la fin de l'application. Vous supprimez alors simplement vos données dans le destructeur et le travail est terminé et nettoyé. C'est le pouvoir de RAII.

Je vous suggère de faire 2, c'est une façon très propre de le faire.


Voici un exemple simple. Au lieu de faire ça

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

Vous ferez ça:

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

et alors

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

Lorsque le programme se termine, la variable statique (qui n'est plus un pointeur) sera détruite et son destructeur sera appelé pour le faire.

C'est écrit juste pour vous donner une idée de comment vous pouvez faire ça.

19
Klaim

Jetez-le dans un pointeur intelligent. Il aura une durée de vie statique et sera détruit après le retour de main:

static std::auto_ptr<T> thePointer;

Une autre option consiste à enregistrer votre propre fonction atexit:

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

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

    return thePointer;
}

Ce qui aura le même effet. Une autre option que vous avez déjà mentionnée est de garder un compteur statique. Notez que vous pouvez réellement envelopper assez efficacement.

15
GManNickG

Du point de vue du système d’exploitation, il n’ya aucun intérêt à libérer de la mémoire lorsque le programme se termine, il ne fait que ralentir la résiliation. La résiliation de votre application détruit tout votre espace d'adressage, elle libère tout vous allouez sur le tas en une seule fois. appeler explicitement free à l’arrêt de l’application ne fait que brouiller les indicateurs dans le tas qui sera jeté de toute façon. 

La principale raison pour laquelle nous nous efforçons de tout libérer de manière explicite est de nous assurer que nous ne perdons pas de mémoire et que notre empreinte mémoire ne croît pas éternellement. 

Mais si vous pouvez être certain que cela est statique, qu'il n'y en aura qu'un, et que vous ne pourrez pas le libérer en toute sécurité tant que tous vos autres objets n'auront pas été libérés, c'est un cas où il vaudrait mieux laisser l'application. la résiliation en prend soin pour vous.

6
John Knoeller

Vous pouvez vous déclarer variable statique en tant que pointeur intelligent, puis lorsque le programme terminé, le pointeur alloué sera libéré.

2
coelhudo

je définirais un compteur statique dans la classe pour suivre le nombre d'instances d'objet au fur et à mesure que le destructeur s'exécute l'exécute décrémente le compteur et si counter == 0 libère la mémoire aussi .. tout comme vous

0
Luca Rocchi