单例析构那点事儿

本文探讨了C++中的单例模式,特别是在游戏服务器开发中的应用。文章指出,虽然单例不析构通常不会有实际问题,但在检查内存泄漏时可能会导致误报。作者提供了模板单例类`CSingleton`的实现,包括一个内部类`CAutoGC`来确保在进程结束时正确析构单例。通过`CSingleton<T>::GetGC()`调用来确保`CAutoGC`实例的构造,从而在程序退出时自动释放单例。文章还给出了两种单例使用示例,并提到线程本地存储的单例需要C++11的`thread_local`支持,并提醒读者,许多C++书籍中的知识可能已过时或不准确。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例是c++中比较常用的设计模式,在游戏服务器开发中很多全局管理器都是用单例实现。其实单例不析构也不会有任何问题,但是有的时候需要查内存泄漏问题那么单例不析构会导致工具报错太多,不利于查找问题。普通单例没有通用性,在我参与的所有游戏项目中都是模板单例,网上有很多单例析构的例子,但是我几乎没有找到有模板单例析构正常的代码。模板单例析构代码如下:

template<typename T>
class CSingleton
{
public:
static T& GetInstance()
{
if (NULL == m_pInstance)
{
m_pInstance = new T();
assert(m_pInstance != NULL);
CSingleton<T>::GetGC();
}
return *m_pInstance;
}
protected:
static T *m_pInstance;
protected:
CSingleton(){}
~CSingleton(){}
private:
CSingleton(const CSingleton &);
CSingleton& operator = (const CSingleton &);
private:
class CAutoGC
{
public:
~CAutoGC()
{
if (nullptr != m_pInstance)
{
delete m_pInstance;
m_pInstance = nullptr;
}
}
};
static CAutoGC m_gc;
static CAutoGC& GetGC() { return m_gc; }
};
template<typename T>
T* CSingleton<T>::m_pInstance = NULL;


template<typename T>
typename  CSingleton<T>::CAutoGC CSingleton<T>::m_gc;


class CTest:public CSingleton<CTest> 
{
public:
CTest() { printf("new test\n"); }
~CTest() { printf("del test\n"); }
};
class CTestEx 
{
public:
CTestEx() { printf("new CTestEx\n"); }
~CTestEx() { printf("del CTestEx\n"); }
};
void ThreadRun()
{
CTest::GetInstance();
CSingleton<CTestEx>::GetInstance();
}
int main(int argc, char* argv[])
{
ThreadRun();
return 0;

}

CSingleton内中有一个私有的内部类,在进程结束之后m_gc成员变量的自动析构会析构单例,其中关键的地方是CSingleton<T>::GetGC();这行代码的调用,没有这行代码那么m_gc成员变量没有任何地方使用那么将不会被构造,没有构造那就更不用说析构了。ThreadRun()函数中展示了两种单例使用的方法。在游戏服务器开发中都比较常用。由于这两种使用方法所以CSingleton<T>::GetGC()这行代码不能用m_pInstance->GetGC();替换。

其实有的项目中还会使用线程本地存储的单例,这种单例要想使用上面的自动析构要支持c++11中thread_local的编译器才行。大家可以在项目中试试。只有自己实践之后才会有更深刻的体会。c++编程书籍很多都是古老的了,现在很多东西都发生了变化,也就是说很多书上的知识已经不适用或者说就是错误的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值