这个单例实现有问题吗?

时间:2012-02-10 14:07:31

标签: c++ design-patterns singleton

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

class MyClass
{
    public:
        MyClass* GetInstance()
        {
            static MyClass instance;
            return &instance;
        }

    private:
        //Disallow copy construction, copy assignment, and external
        //default construction.
};

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

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

5 个答案:

答案 0 :(得分:3)

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

符合C ++ 11的编译器必须以线程安全的方式实现它;但是,较旧的编译器可能不会。如果您有疑问,并且您并不特别想要延迟初始化,则可以在启动任何线程之前通过调用访问器来强制创建对象。

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

界面中有两个问题:

  • 您应该返回参考
  • 您应该使用析构函数或delete运算符private

此外,在被破坏后尝试使用此类的风险很小。

关于你的多线程问题(以及我猜想的初始化):它在C ++ 11中很好,并且无论如何在好的C ++编译器上都很好。

答案 3 :(得分:0)

除了在多线程场景中 - 没有。好吧 - 让我限定一下,施工是懒惰的(所以第一次打电话可能会受到打击)和破坏 - 好吧,没有保证(除了它将 - 在某些时候)

答案 4 :(得分:0)

一般来说,方法中局部变量的限定符static不能保证变量只创建一次。如果该方法由不同的线程调用,则可以为每个线程创建一次这么多次,就像许多线程一样。它不应该与类的静态成员混淆,后者在程序启动之前创建一次。局部静态变量的线程安全性取决于c ++的特定实现。有用的链接:Are function static variables thread-safe in GCC?

希望它有所帮助。