谈谈 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代码优化及工程级应用>>
的改进单例模式这一章节
评论