简体   繁体   中英

How to free static member variable in C++?

Can anybody explain how to free memory of a static member Variable? In my understanding it can only be freed if all the instances of the class are destroyed. I am a little bit helpless at this point...

Some Code to explain it:

class ball
{
    private:
    static SDL_Surface *ball_image;
};
//FIXME: how to free static Variable?
SDL_Surface* ball::ball_image = SDL_LoadBMP("ball.bmp");

The pointer itself will be around until the program shuts down. However, what it points to is fair game. You can free that at any time.

If what you're worried about is memory leaks, then you have a few options that I see:

  1. Just let it leak. All the memory from the program will be released when it shuts down. However, if you need more than just the memory being freed (like you want a destructor to run), then that's not such a good idea.

  2. Have a static member variable which keeps track of how many instances of the class have been created. Free the memory when it reaches zero and reallocate it if it goes above 0 again.

  3. Have a function of some kind which runs when the program is shutting down and have it worry about freeing the memory.

  4. If you can, make it so that it's not a pointer anymore. If it's not a pointer, you don't have to worry about it.

  5. Use a smart pointer or auto_ptr . That way, when the pointer itself is destroyed, the memory will be taken care of.

Personally, I'd advise 4 if you can and 5 if you can't, but you have several options.

From the sound of it, you don't really want a pointer at all. In fact, since this is coming from a factory function in a C library, it isn't really a "first-class" C++ pointer. For example, you can't safely delete it.

The real problem (if there is one) is to call SDL_FreeSurface on it before the program exits.

This requires a simple wrapper class.

struct smart_sdl_surface {
    SDL_Surface *handle;

    explicit smart_sdl_surface( char const *name )
        : handle( SDL_LoadBMP( name ) ) {}
    ~smart_sdl_surface()
        { SDL_FreeSurface( handle ); }
};

class ball
{
    private:
    static smart_sdl_surface ball_image_wrapper;
    static SDL_Surface *& ball_image; // reference to the ptr inside wrapper
};
smart_sdl_surface ball::ball_image_wrapper( "ball.bmp" );
SDL_Surface *&ball::ball_image = ball::ball_image_wrapper.handle;

When the program initializes, the constructor is called and the file is read. When the program exits, the destructor is called and the object is destroyed.

The static member variable in this case is a pointer. You can't free it, but you can free what it points to:

SDL_FreeSurface(ball_image);

You might then want to set ball_image to 0, to record the fact that you no longer have an image.

it can only be freed if all the instances of the class are destroyed

If by "the class" you mean ball , then no. Static members of ball continue to exist regardless of how many instances of ball there are. The only way a static member might be destroyed before program exit is if you do some (implementation-dependent) thing like unloading the dll which contains the class. But in this case the static member is just a pointer, so (1) destroying it will just destroy the pointer, not the pointee, and (2) there is no need to destroy a pointer anyway, it doesn't occupy significant resources.

如果必须将静态成员指向堆分配的内存,我会使成员成为智能指针。

A static member exists completely independently of all instances of the class it is a member of. You can delete the pointer at any point in the program. Whether this makes sense semantically, is another issue, of course.

I agree with Jonathan M Davis' answer, but another option you could consider is pulling your images and other resources out of your "domain objects" and into a ResourceManager class, or something along those lines.

The ResourceManager could either be static, or instance-based, and would provide the logic to load and delete resources, needed by the rest of our application.

Classes needing resources could just hold a reference or a pointer to the global resource manager, and request resources from the manager, rather than managing them themselves.

Static member variables don't need to be deleted. If you have one within a class, is because you want to use it at any time during the entire life of the programme. Once the programme finishes, the Operating System claims back the total memory assigned to it, including any undeleted memory space.

Of course, if you insist in deleting it, you can create a special static member method for doing it and invoke the method at a desired point in the programme. But I woudn't recommend it to anyone, because it violates the semantic integrity of the static member variables, increasing so the complexity and the likelihood for causing troubles as the programme grows.

Working with a static variable where the memory is dynamically allocated, it is better to go with smart_pointer or a method where memory is cleared manually.

Clearing the memory of static varibles in the destructor will not work for the below case: As static members exist as members of the clas s rather than as an instance in each object of the class . So if someone access a static variable using :: and dynamically allocate memory, the destructor will not come in picture and the memory will not get deleted, as there is no object created.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM