谈谈 C++ 单例模式

一个类只有一个实例化对象 全局可以使用 
单例模式的基本实现:包含单例模式的实现,线程安全,以及生命周期等 单例模式的模板实现, 多模块调用单例存在的问题 
单例模式的基本实现
私有的构造函数, 拷贝构造函数,以及 operator=, 保证其不能够在类的外部进程对象构造,拷贝等操作。GetInstance是一个公有的静态成员函数,用来构造这个类唯一的实例对象m_objConfig, 并且返回给使用者。
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig = = nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig *m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;
单例模式生命周期
单例创建的时机
class SingletonConfig{public:static SingletonConfig * GetInstance(){return m_objConfig;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig *m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = new SingletonConfig;
单例释放的时机
class SingletonConfig{public:static SingletonConfig * GetInstance(){static SingletonConfig objConfig;return &objConfig;}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };};
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig == nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}static void ReleaseInstance(){if (m_objConfig){delete m_objConfig;m_objConfig = nullptr;}}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig* m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;
线程安全
static SingletonConfig * GetInstance(){static SingletonConfig objConfig;return &objConfig;}
static SingletonConfig * GetInstance(){if (m_objConfig == nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}
使用 std::lock_guard去多线程保证互斥双重的 m_objConfig == nullptr检查,第一次是为了效率,当单例对象已经在的时候,就不需要互斥锁了;第二次是进入锁范围之后,要查看下,是否有其他线程已经创建了单例对象,如果还没有创建才进行创建。
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig == nullptr){std::lock_guard<std::mutex> guard(m_mutex);if (m_objConfig == nullptr){m_objConfig = new SingletonConfig;}}return m_objConfig;}static void ReleaseInstance(){if (m_objConfig){delete m_objConfig;m_objConfig = nullptr;}}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig* m_objConfig;static std::mutex m_mutex;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;std::mutex SingletonConfig::m_mutex;
单例模式的模板实现以及可能的问题
template<typename T>class CommonSingleton{public:static T* GetInstance(){if (m_objSingle == nullptr){std::lock_guard<std::mutex> guard(m_mutex);if (m_objSingle == nullptr){m_objSingle = new T;}}return m_objSingle;}static void ReleaseInstance(){if (m_objSingle){delete m_objSingle;m_objSingle = nullptr;}}private:CommonSingleton() { ; };CommonSingleton(const CommonSingleton&) { ; };CommonSingleton& operator= (const CommonSingleton&) { ; };private:static T* m_objSingle;static std::mutex m_mutex;};template<typename T>T* CommonSingleton::m_objSingle = nullptr; template<typename T>std::mutex CommonSingleton::m_mutex; 
CommonSingleton<TestClass>::GetInstance();模板参数接受的类,可以是这种:默认暴露给用户,可以构造,拷贝,赋值的类,这样便可以重新创造多个对象。这种方式缺乏了本人所理解的 防御性编程的思路。当使用模板实例化的时候,同一种模板参数的类,在多个不同的模块中其实都会有自己的实例化对象。比如有A和B两个模块,并且均调用了 CommonSingleton, 其实在A和B中存在不同的::GetInstance(); TestClass对象,这样也违背了一个程序一个实例化对象的初衷。当然只有一个工程不影响。对于非模板的实现,一般将单例实现的类从模块导出,将实现放在.cpp文件中,那么这种多个工程对同一种单例的类只会有一个实例化对象。个人觉得这一点比较重要,需要读者多多体会。
总结
参考
<中的Singletons实作技术这一章节> <<深入应用C++11代码优化及工程级应用>>的改进单例模式这一章节
评论

