C ++: лучший способ уничтожить статические вещи - PullRequest
5 голосов
/ 28 августа 2010

Когда у меня есть класс, содержащий статические вещи, как я могу наилучшим образом освободить память в конце приложения?

Foo.h

class GLUtesselator;

class Foo
{
private:
    static GLUtesselator *tess;
public:
    Foo();
    virtual ~Foo();
}

Foo.cpp

#include "Foo.h"

#include <GL/glu.h>

GLUtesselator *Foo::tess = gluNewTess(); // System call

Foo::Foo() {}
Foo::~Foo()
{
     // And of course I don't want to destruct it here,
     // because I'm going to use the tesselator in other instances of Foo
     // Otherwise:
     // gluDeleteTess(tess);
}

Существуют ли лучшие альтернативы созданию метода для удаления статических объектов и вызова его при завершении работы приложения?
Или я могу сказать: "О, что угодно, приложение закрывается. ОС освободит память ... "?

Спасибо

Ответы [ 4 ]

7 голосов
/ 28 августа 2010

Simple. Не делайте статический член указателем.
Тогда он будет правильно построен и разрушен.

foo.h

#include <GL/glu.h>

class Foo
{
    private:
        static GLUtesselator  tess;
    public:
                 Foo();
        virtual ~Foo();
};

foo.cpp

// 
GLUtesselator  Foo::tess;

Если вам нужно использовать gluNewTess () и gluDeleteTess (), вы можете использовать общий указатель. У меня нет компилятора, поэтому точное использование может быть не совсем правильным. Но shared_ptr обладает этой способностью.

foo.h

#include <GL/glu.h>

typedef std::shared_ptr<GLUtesselator,void (*)(GLUtesselator*)> AutoGluTess;
class Foo
{
    private:
        static AutoGluTess  tess;
    public:
                 Foo();
        virtual ~Foo();
};

foo.cpp

// 
AutoGluTess    Foo::tess(gluNewTess(), &gluDeleteTess);
2 голосов
/ 28 августа 2010

для глобальных статических переменных:

CFoo* pFoo= NULL;

void DoneFoo()
{
    delete pFoo;
}

void Init()
{
    pFoo= new CFoo();
    atexit(DoneFoo);
}

или

class CFoo
{
     ......
};

#define NewFoo(F_name)                                                             \
    CFoo* F_name##Init();                                                          \
    void  F_name##Done();                                                          \
    CFoo* F_name= F_name##Init();                                                  \
    CFoo* F_name##Init()  { CFoo* F= new CFoo(); atexit(F_name##Done); return F; } \
    void  F_name##Done()  { delete F_name; }    

NewFoo(F1);

для статических переменных-членов:

class CFoo
{
    static int* pKuku;
    static void DoneKuku() { delete pKuku;                     }
    static int* InitKuku() { atexit(DoneKuku); return new int; }
public:
};

int* CFoo::pKuku= CFoo::InitKuku();

Я не думаю, что это хорошая идея, чтобы ОС автоматически освобождала память, потому что у вас будут утечки памяти. Когда у вас есть «законные» утечки памяти - будет труднее заметить «незаконные» утечки, поэтому вы должны стремиться к тому, чтобы вообще не было утечек памяти.

2 голосов
/ 28 августа 2010

Вам не нужно его уничтожать.Все известные мне операционные системы правильно освободят память и освободят все ресурсы, удерживаемые объектом при завершении приложения (Примечание: деструктор не будет вызываться автоматически, но ресурсы будут освобождены).

Если вы действительно хотите уничтожить его, либо

  1. Не используйте указатель, как описывает Мартин Йорк,
  2. Или (если вам нужен указатель), используйте auto_ptr или tr1::unique_ptr, так что pointee автоматически удаляется, когда он выходит из области видимости (который находится в конце приложения для статических переменных).
1 голос
/ 28 августа 2010

Так как он статический, будет только один экземпляр. Если этот GLUtesselator не очень большой, я сомневаюсь, что вам когда-нибудь понадобится освободить его самостоятельно.

как вы сказали: «О, как бы то ни было, приложение закрывается. ОС освободит память ...»

...