Singleton实例声明为GetInstance方法的静态变量

我已经看到实例变量在GetInstance方法中被声明为静态变量的Singleton模式的实现。 喜欢这个:

SomeBaseClass &SomeClass::GetInstance()
{
   static SomeClass instance;
   return instance;
}

我看到了这种方法的以下积极方面:

  • 代码更简单,因为编译器只负责在第一次调用GetInstance时创建此对象。
  • 代码更安全,因为没有其他方式可以获取对实例的引用,但是使用GetInstance方法,并且没有其他方法可以更改实例,但是在GetInstance方法内部。
  • 这种方法的消极方面是什么(除了这不是OOP-ish)? 这是线程安全的吗?


    在C ++ 11中它是线程安全的:

    §6.7[stmt.dcl] p4如果控制在初始化变量时同时输入声明,则并发执行应等待初始化完成。

    在C ++ 03中:

  • 在g ++下它是线程安全的。
    但是这是因为g ++显式添加了代码来保证它。
  • 一个问题是,如果你有两个单身人士,他们在施工和销毁期间尝试使用彼此。

    阅读本文:查找C ++静态初始化顺序问题

    这个问题的一个变种是,如果从全局变量的析构函数访问单例。 在这种情况下,单例已经被销毁,但get方法仍然会返回对被销毁对象的引用。

    有办法解决这个问题,但它们很混乱,不值得去做。 只是不要从全局变量的析构函数中访问单例。

    更安全的定义,但丑陋:
    我相信你可以添加一些适当的宏来整理这些

    SomeBaseClass &SomeClass::GetInstance()
    {
    #ifdef _WIN32 
    Start Critical Section Here
    #elif  defined(__GNUC__) && (__GNUC__ > 3)
    // You are OK
    #else
    #error Add Critical Section for your platform
    #endif
    
        static SomeClass instance;
    
    #ifdef _WIN32
    END Critical Section Here
    #endif 
    
        return instance;
    }
    

    如图所示,它不是线程安全的。 C ++语言在线程上保持沉默,所以你没有语言的内在保证。 您将不得不使用平台同步原语,例如Win32 :: EnterCriticalSection()来保护访问。

    编译器会在第一次调用时插入一些(非线程安全的)代码来初始化静态instance ,这很可能是在函数体开始执行之前(因此在可以调用任何同步之前。)

    使用指向SomeClass的全局/静态成员指针,然后在同步块内初始化将会证明实现起来不太麻烦。

    #include <boost/shared_ptr.hpp>
    
    namespace
    {
      //Could be implemented as private member of SomeClass instead..
      boost::shared_ptr<SomeClass> g_instance;
    }
    
    SomeBaseClass &SomeClass::GetInstance()
    {
       //Synchronize me e.g. ::EnterCriticalSection()
       if(g_instance == NULL)
         g_instance = boost::shared_ptr<SomeClass>(new SomeClass());
       //Unsynchronize me e.g. :::LeaveCriticalSection();
       return *g_instance;
    }
    

    我没有编译这个,所以它仅用于说明目的。 它也依赖于boost库来获得与你最初的例子相同的生命周期(或那里)。 你也可以使用std :: tr1(C ++ 0x)。


    根据规格,这也应该在VC ++中工作。 任何人都知道它是否?

    只需添加关键字volatile。 如果msdn上的doc是正确的,visual c ++编译器就应该生成互斥量。

    SomeBaseClass &SomeClass::GetInstance()
    {
       static volatile SomeClass instance;
       return instance;
    }
    
    链接地址: http://www.djcxy.com/p/78841.html

    上一篇: Singleton instance declared as static variable of GetInstance method

    下一篇: Can any one provide me a sample of Singleton in c++?