这个单例实现有问题吗

Is there an issue with this singleton implementation?

本文关键字:有问题 实现 单例      更新时间:2023-10-16

我通常习惯于用这种方式实现单例模式,因为它非常容易:

class MyClass
{
    public:
        MyClass* GetInstance()
        {
            static MyClass instance;
            return &instance;
        }
    private:
        //Disallow copy construction, copy assignment, and external
        //default construction.
};

这似乎比创建静态实例指针、在源文件中初始化它以及在带有保护的实例函数中使用动态内存分配要容易得多。

有没有我没有看到的缺点?对我来说,它看起来是线程安全的,因为我认为第一个到达第一行的线程会导致实例化,而且它看起来很好,很简洁。我想肯定有一个问题我没有看到,因为这并不常见-我想在继续使用它之前得到一些反馈

这不是一个固有的线程安全解决方案:在构造实例时,另一个线程可以抢占并尝试获取实例,从而导致双实例或使用未构造的实例。

这是由几个编译器通过添加一个保护来处理的(在gcc中,我认为有一个标志可以禁用它),因为没有办法用用户定义的互斥来保护它。

缺点是无法控制对象何时被销毁。如果其他静态对象试图从其析构函数访问它,这将是一个问题。

一个兼容C++11的编译器必须以线程安全的方式实现这一点;然而,较旧的编译器可能不会。如果您有疑问,并且不特别希望延迟初始化,可以在启动任何线程之前通过调用访问器来强制创建对象。

接口中有两个问题:

  • 您应该返回一个引用
  • 您应该将析构函数或delete运算符设为private

此外,在该类被销毁后,尝试使用该类的风险很小。

关于您的多线程问题(我想还有初始化):它在C++11中很好,而且在好的C++编译器上已经好了很长一段时间。

除了在多线程场景中-没有。好吧,让我限定一下,构建是懒惰的(所以第一个调用可能会命中)和破坏-好吧,不能保证(除了它会在某个时候)

一般来说,方法中局部变量的限定符static不能保证只创建一次变量。如果该方法由不同的线程调用,那么它可以为每个线程创建一次,因为很多线程都调用了它。不应该将它与类的静态成员混淆,后者在程序启动前创建一次。局部静态变量的线程安全性取决于c++的特殊实现。有用的链接:函数静态变量在GCC中是线程安全的吗?

希望能有所帮助。