Search code examples
c++stlsdl

Order of Precedence: Smart Pointer and Class Destructor


Suppose we have a class with a smart pointer. This class initializes a subsystem that the smart pointer relies on: similarly, this class closes the subsystem upon destruction.

If the smart pointer relies on said subsystem to free its memory, then if the destructor closes the subsystem first an issue arises.

class FontManager {
public:
    FontManager() {
        if(TTF_Init() < 0) {
            printf( "SDL_ttf could not init! SDL_ttf Error: %s\n", TTF_GetError() );
            return;
        }
    }

~FontManager() {
    TTF_Quit();
}

std::unique_ptr<TTF_Font> font;

void operator()(TTF_Font* font) const { TTF_CloseFont(font); }
};

If I were using raw pointers the destructor would look like this.

~FontManager() {
    // font is raw pointer
    TTF_CloseFont(font);
    TTF_Quit();
}

So, what gets called first, the pointer's destructor or the class' destructor?


Solution

  • Just as subobjects are constructed at the beginning of a class’s constructor (in the member initializer list, perhaps implicitly), they are destroyed at the end of the destructor (in the reverse order of their construction, as usual).

    You can of course reset your pointers manually in your destructor; they will still be destroyed at the end of it, but with no effect. But the real answer is to encapsulate the subsystem (initialization) as its own resource, add an instance of that new class as an earlier member, and then let the containing class use the implicit destructor. This has the additional benefit of guaranteeing that the subsystem is initialized when you use it to allocate the smart pointer’s object.