MProgrammer MProgrammer - 3 months ago 7
C++ Question

Is std::unique_ptr deletion order guaranteed?

I am making a global singleton that controls my application and I want the subsystems to startup and shutdown in a specific order.

class App
{
public:
App();
~App();

void start();
void run();
void shutdown();

private:
std::unique_ptr<DisplayManager> displayManager;
std::unique_ptr<Renderer> renderer;
};


The constructor creates the pointers in the correct order

App::App()
{
displayManager = std::unique_ptr<DisplayManager>(new DisplayManager);
renderer = std::unique_ptr<Renderer>(new Renderer);
}


and I want the unique_ptrs to be deallocated in the reverse order. Does std::unique_ptr have a guarantee that the memory will be deallocated in this order?

I thought about making all of the managers global singletons, but felt this way would be better if I could make it work.

EDIT: It has been brought to my attention that the actual problem is the order that an instance variables members get destructed. In that case is there a guaranteed order for that?

Answer

std::unique_ptr doesn't control when it's destructor is called. Instead it is where it is declared that determines what order it is destructed in.

Class members are constructed in the order they are declared in the class body and are destroyed in the reverse of that order. So in your case when a App is constructed displayManager is constructed first and then renderer is constructed. When the App instance is destroyed then renderer is destroyed first and then displayManager is destroyed.


Also note that in

App::App()
{
    displayManager = std::unique_ptr<DisplayManager>(new DisplayManager);
    renderer = std::unique_ptr<Renderer>(new Renderer);
}

You are doing assignment to default constructed unique_ptrs. You need to use the member initialization list like

App::App(): displayManager(new DisplayManager), renderer(new Renderer) {}

If you do not want to default construct the pointers and then assign to them.