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?
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_ptr
s. 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.
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_ptr
s 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_ptr
s' declaration inside App
that counts.
So, though the destruction order is guaranteed, it may not be the order you were expecting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With