网站首页> 文章专栏> 如何检测单例是否已经析构
如何检测单例是否已经析构
编辑时间:2024-08-07 12:17:44 作者:qicosmos 0条评论

单例本质是一个静态变量,它只会在程序退出的时候才会析构,如果有这样一个场景,在程序退出的时候调用了单例,但这时候单例已经析构了,调用就会出错。该如何解决这个问题呢?

一个巧妙的方法是通过一个全局变量去检测,代码如下:

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 出来的,它不会删除,不用担心单例失效的问题了。进程退出时会释放堆内存,也不会有内存泄漏的问题,这种方式更简单,不需要一个额外的全局变量去检测了。

最后附上一首小诗:

见街边儿童吃雪糕

疾走行人避夏炎,闲情童子坐街边。

冷冰在手消烦暑,寒雪清心化乐泉。


    出自:purecpp.cn

    地址: www.purecpp.cn

    转载请注明出处!


来说两句吧
登录才能发表评论。
最新评论
Absolutely

purecpp

一个很酷的modern c++开源社区


[社区开源项目列表,点击前往]


purecpp社区自2015年创办以来,以“Newer is Better”为理念,相信新技术可以改变世界,一直致力于现代C++研究、应用和技术创新,期望通过现代C++的技术创新来提高企业生产力和效率。


社区坚持只发表原创技术文章,已经累计发表了一千多篇原创C++技术文章;


组织了十几场的C++沙龙和C++大会,有力地促进了国内外C++开发者之间的技术交流;


开源了十几个现代C++项目,被近百家公司所使用,有力地推动了现代C++在企业中的应用。


期待更多的C++爱好者能参与到社区C++社区的建设中来,一起为现代C++开源项目添砖加瓦,一起完善C++基础设施和生态圈。


微信公众号:purecpp, 社区邮箱: purecpp@163.com


友情链接