C++ 中单例模式中的内存释放

Memory deallocation in the Singleton pattern in C++

提问人:koegl 提问时间:7/6/2023 更新时间:7/6/2023 访问量:75

问:

我正在尝试理解在 C++ 中使用单例模式时的内存释放。

我发现所有使用的例子都没有明确使用 ,这对我来说意味着内存泄漏。newdelete

他们为什么不使用?delete

这是因为根据定义,我们只有一个单例实例,该实例及其动态分配的内存将在程序终止后被删除?

C++ 内存管理 单例

评论

0赞 Will Moffat 7/6/2023
是的,我认为这是对的。只要你从不更改单例的实例,你就可以依靠它在终止时被清除。
2赞 john 7/6/2023
当程序退出时,您的单例将被销毁。当程序退出时,所有内存都将返回给操作系统,因此没有内存泄漏。
2赞 john 7/6/2023
但是,如果您的单例需要析构函数来释放资源(例如数据库连接),那么调用该析构函数非常重要。所以你的例子对这种单例不利。
1赞 user7860670 7/6/2023
当程序退出时,分配的对象不会被销毁。析构函数中不执行清理操作。是的,内存泄漏。newdelete
1赞 pptaszni 7/6/2023
取决于上下文。 不需要显式.无论如何,具体的答案需要一个具体的例子。std::unique_ptr<Singleton> instance{new Singleton};delete

答:

0赞 Mike Tyukanov 7/6/2023 #1

这是 Singleton 性质的一部分。

与普通的全局变量相比,Singleton 最常见的用途是确保它在从其他全局变量和文件级静态对象调用时能够正常工作。

对于不同的翻译单元,文件级全局变量的初始化和销毁顺序都是不确定的,分别是之前和之后的某个时间段。例如,当一个全局对象调用时,比如说,其中 theLog 只是另一个全局对象,theLog 可以尚未初始化,因此对于此类日志记录,我们需要一个 Singleton:当我们调用静态函数来获取我们的日志对象时,无论何时调用,都会构造该对象(函数级静态的首遍初始化规则)。main()theLog.log("starting thisGlobal");

现在,如果我们删除该静态对象会发生什么?我们可以在哪里删除它?我们可以在 的末尾做到这一点,但这违背了目的:当其他全局变量的析构函数调用它时,我们的单例将被删除。我们可以在 之后删除全局变量的析构函数之一,但对于全局变量,破坏顺序与构造顺序一样不确定,我们无法确保该对象确切地是最后一个析构函数,并且他可以安全地删除我们的单例。main()main()

在某些情况下,编译器可以延迟初始化,并且有一些非标准的方法来确定全局变量的初始化/销毁顺序,但是如果我们使用它,我们就不需要单例了。只需将该类的全局对象设置为第一个初始化对象,最后一个结束即可。

因此,要么我们不能摧毁单例,要么我们根本不需要单例。

至于内存泄漏 -- 这取决于你如何定义泄漏。由于您只分配一次此内存,因此它几乎无法与静态内存区分开来。检漏仪的误报通常可以被抑制。