Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 583
Xeronate Avatar asked Aug 16 '16 16:08

Xeronate


2 Answers

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) {}
// or if you want to be in the don't use new camp
App::App(): displayManager(std::make_unique<DisplayManager>()), renderer(std::make_unique<Renderer>()) {}

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

like image 73
NathanOliver Avatar answered Nov 10 '22 10:11

NathanOliver


Yes, the destruction order is guaranteed.

Each deleter will be invoked as soon as the owing std::unique_ptr is destroyed ref, and the std::unique_ptrs are destroyed in reverse order of their construction when they all go out of scope togetherref.

However, this order has no direct relationship to the order of your assignments inside App::App() — you could swap them around and nothing would change. It's the order of the std::unique_ptrs' declaration inside App that counts.

So, though the destruction order is guaranteed, it may not be the order you were expecting.

like image 36
Lightness Races in Orbit Avatar answered Nov 10 '22 09:11

Lightness Races in Orbit