單例模式保證該類對象隻建立一個,且提供全局唯一的通路點。具體實作而言,主要有三個問題:對象初始化,通路和銷毀。
對象初始化。常見的初始化形式有四種:靜态對象成員,靜态指針成員,靜态本地對象,靜态本地指針。對象成員在main函數之前就已經初始化了,不能使用任何系統啟動才加載的配置項;而指針成員同理,但可以實作延遲執行個體化。這兩種形式在多線程情況下,都需要加鎖進行執行個體化(從文法上,靜态成員對象能保證對象唯一性嗎?),進而防止産生多個副本。對于本地變量,在第一次通路該靜态方法時,進行初始化,要求該對象必須是is_default_constructible,且c11從文法上保證其并發情況的下的唯一性。而對于本地指針,則可以進行定制化的初始化,但同時也要求通過鎖進行并發控制,反之建立多個副本。是以本地對象優于成員對象,因為有并發保證,而且可以延遲初始化;而當對象初始化和通路在不同的方式裡面時,指針成員優于本地變量,因為靜态本地變量不能提供跨方法通路。是以,初始化代碼如下:
// default constructible type
Tp& Instance() { static Tp s_instance; return s_instance;}
// non-default constructible type
template<class... Args>
Tp& Instance(Args&& args...) {
std::call_once( s_init_once_flag, [&](){
s_pInstance = std::unique_ptr<Tp>(new Tp(std::forward<Args>(args)...)); } );
return *s_pInstance;
}
對象通路。對于default constructible type,自然通過Instance()通路;而對于non-default constructible type既可以通過初始化的Instance(args...)也可以通過Instance()來通路。
對象銷毀。對于default constructible type,系統exit的時候會自動銷毀靜态本地變量;對于non-default constructible type則由unique_ptr來保證銷毀。
template
class Singleton : public Noncopyable
{
public:
static Tp& Instance()
{
// 1>c11 guarantees that a local static variable is only run once
// this ensures thread-safety in initializing singletion class
// in concurrecy context
// 2>it won't init unless it's first accessed
// 3>if g_instance works as a static member variable
// it will be inited before main, which means
// its initialization can't take advantage of
// info known only once the program is up and running
// ### it's unnecessary to be zero-argument default constructed
// ### it should support various constructor
static Tp s_instance;
return s_instance;
}
// noncopyable
// Singleton
& operator=( const Singleton
& ) = delete;
// Singleton( const Singleton
&) = delete;
protected:
// if a class supports singleton, it has to inherit class Singleton
Singleton(){};
virtual ~Singleton(){};
};
template
class Singleton
: public Noncopyable { public: template
static Tp& Instance(Args&&... args) { std::call_once( s_inited_once_flag, [&](){ s_pInstance = std::unique_ptr
( new Tp(std::forward
(args)... ) ); // std::atexit(destroy); }); return *s_pInstance; } static Tp& Instance() { if( nullptr == s_pInstance ) { throw std::logic_error(std::string() + typeid(Tp).name() + " is not inited!\n"); } return *s_pInstance; } // noncopyable // Singleton
& operator=( const Singleton
& ) = delete; // Singleton( const Singleton
&) = delete; protected: // if a class supports singleton, it has to inherit class Singleton Singleton(){}; virtual ~Singleton(){}; private: static std::unique_ptr
s_pInstance; static std::once_flag s_inited_once_flag; /* static void destroy() { if( nullptr != s_pInstance ) { delete s_pInstance; s_pInstance = nullptr; std::cout << typeid(Tp).name() << " get deleted in " << __PRETTY_FUNCTION__ << '\n'; } } */ }; template
std::unique_ptr
Singleton
::s_pInstance; template
std::once_flag Singleton
::s_inited_once_flag;