是否保证std::unique_ptr的删除顺序

Is std::unique_ptr deletion order guaranteed?

本文关键字:ptr 删除 顺序 unique std 是否      更新时间:2023-10-16

我正在创建一个控制我的应用程序的全局单例,并且我希望子系统以特定的顺序启动和关闭。

class App
{
public:
    App();
    ~App();
    void start();
    void run();
    void shutdown();
private:
    std::unique_ptr<DisplayManager> displayManager;
    std::unique_ptr<Renderer> renderer;
};

构造函数按正确顺序创建指针

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

和我希望unique_ptrs以相反的顺序被释放。std::unique_ptr是否保证内存将按此顺序被释放?

我想让所有的管理器都是全局单例的,但我觉得如果我能让它工作的话,这种方式会更好。

编辑:我注意到实际问题是实例变量成员被销毁的顺序。这样的话,有保证的订单吗?

std::unique_ptr不控制何时调用它的析构函数。相反,它的声明位置决定了它的销毁顺序。

类成员按其在类体中声明的顺序构造,并按相反的顺序销毁。在你的例子中,当构建App时首先构建displayManager,然后构建renderer。当App实例被销毁时,renderer将首先被销毁,然后displayManager将被销毁。


还要注意在

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

您正在对默认构造的unique_ptr s进行赋值。您需要使用像

这样的成员初始化列表
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>()) {}

如果您不想默认构造指针,然后对其进行赋值,

是,销毁顺序是有保证的。

每个deleter将在当前的std::unique_ptr被销毁后立即被调用ref,并且当std::unique_ptr同时离开作用域ref时,它们将以与其构造相反的顺序被销毁。

但是,这个顺序与App::App() —你可以把它们调换一下,没有什么变化。Appstd::unique_ptr s声明的顺序才是最重要的。

因此,尽管销毁顺序是有保证的,但它可能不是您期望的顺序。