gpt4 book ai didi

c++ - 为什么要避免在 C++ 中使用单例

转载 作者:太空狗 更新时间:2023-10-29 20:59:08 25 4
gpt4 key购买 nike

人们到处都在使用单例。最近从 stackoverflow 上读到一些线程,认为在 C++ 中应该避免单例,但不清楚为什么会这样。

有些人可能会担心未删除指针的内存泄漏,异常之类的东西会跳过内存回收代码。但是 auto_ptr 会解决这个问题吗?

最佳答案

一般来说,正如另一个答案中提到的,您应该避免使用可变的全局数据。它引入了跟踪代码副作用的困难。

但是您的问题是专门针对 C++ 的。例如,您可以拥有值得在单例中共享的全局不可变数据。具体而言,在 C++ 中,几乎不可能在多线程环境中安全地初始化单例。

多线程环境

您可以使用“首次使用时构造”习惯用法来确保单例在需要时正确初始化:http://www.parashift.com/c++-faq-lite/static-init-order.html .

但是,如果您有 2 个(或更多)线程都在同一时间第一次尝试访问单例,会发生什么情况?如果共享的不可变数据是您的 calculateSomeData 线程所需的数据,并且您同时初始化其中的几个线程,那么这种情况并不像看起来那么牵强。

阅读上面链接的 C++ FAQ Lite 中的讨论,您首先会发现这是一个复杂的问题。添加线程会使它变得更加困难。

在 Linux 上,编译器使用 gcc 为您解决了这个问题 - 静态变量在互斥体中初始化并且代码对您来说是安全的。这是一个增强,标准不需要这样的行为。

在 MSVC 中,编译器不为您提供此实用程序,您会遇到崩溃。您可能会想“没关系,我会在第一次使用初始化时放置一个互斥体!”然而,互斥量本身也存在完全相同的问题,它本身需要是静态的。

确保您的单例对线程使用安全的唯一方法是在任何线程启动之前在程序中尽早初始化它。这可以通过一个技巧来实现,该技巧会导致在调用 main 之前初始化单例。

依赖其他单例的单例

这个问题基本上可以通过首次使用时的构造来解决,但是如果您在初始化任何线程之前遇到初始化它们的问题,则可能会引入新的问题。

跨平台兼容性

如果您计划在多个平台上使用您的代码并编译共享库,则可能会遇到一些问题。因为没有指定 C++ ABI 接口(interface),每个编译器和平台处理全局静态的方式不同。例如,除非在 MSVC 中显式导出符号,否则每个 DLL 都将有自己的单例实例。在 Linux 上,单例将在共享库之间隐式共享。

关于c++ - 为什么要避免在 C++ 中使用单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25345645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com