网站首页> 文章专栏> 如何检测单例是否已经析构
单例本质是一个静态变量,它只会在程序退出的时候才会析构,如果有这样一个场景,在程序退出的时候调用了单例,但这时候单例已经析构了,调用就会出错。该如何解决这个问题呢?
一个巧妙的方法是通过一个全局变量去检测,代码如下:
inline std::atomic<bool> g_has_destruct = false;
class Singleton {
public:
Singleton(const Singleton&) = delete;
Singleton& operator = (const Singleton&) = delete;
static Singleton& instance(){
static Singleton instance;
return instance;
}
private:
Singleton() = default;
~Singleton() {
g_has_destruct = true;
}
};
auto g_thd = std::thread([]{
if(!g_has_destruct)
Singleton::instance();
});
auto inst = Singleton::instance();
int main() {
g_thd.detach();
}
在单例的析构函数中设置全局变量g_has_destruct为true,当程序退出时会析构Singleton,假设析构之后g_thd线程函数执行,这时候会去检查g_has_destruct,从而避免调用Singleton。问题是全局变量g_has_destruct不是也会析构吗,通过它去判断不会有问题吗?全局变量g_has_destruct会析构,但是它没有析构函数,所以它的值在析构的时候不会变,只要单例析构的时候设置过它,后面拿它的值就是设置时的值不会变化,所以使用它去检测单例是否析构是没问题的。
另外一种方法是避免单例对象析构。
class Singleton {
public:
Singleton(const Singleton&) = delete;
Singleton& operator = (const Singleton&) = delete;
static Singleton& instance(){
static Singleton* instance = new Singleton();
return *instance;
}
private:
Singleton() = default;
};
由于Singleton是new 出来的,它不会删除,不用担心单例失效的问题了。进程退出时会释放堆内存,也不会有内存泄漏的问题,这种方式更简单,不需要一个额外的全局变量去检测了。
最后附上一首小诗:
见街边儿童吃雪糕
疾走行人避夏炎,闲情童子坐街边。
冷冰在手消烦暑,寒雪清心化乐泉。
地址: www.purecpp.cn
转载请注明出处!
purecpp
一个很酷的modern c++开源社区
purecpp社区自2015年创办以来,以“Newer is Better”为理念,相信新技术可以改变世界,一直致力于现代C++研究、应用和技术创新,期望通过现代C++的技术创新来提高企业生产力和效率。
社区坚持只发表原创技术文章,已经累计发表了一千多篇原创C++技术文章;
组织了十几场的C++沙龙和C++大会,有力地促进了国内外C++开发者之间的技术交流;
开源了十几个现代C++项目,被近百家公司所使用,有力地推动了现代C++在企业中的应用。
期待更多的C++爱好者能参与到社区C++社区的建设中来,一起为现代C++开源项目添砖加瓦,一起完善C++基础设施和生态圈。
微信公众号:purecpp, 社区邮箱: purecpp@163.com