单例模式的析构学习

1、例子

如果单例对象是类的static成员,那么在程序结束时不会调用类的析构函数,如下:

cpp 复制代码
#include <iostream>
using namespace std;
 
class A{
private:
    static A* m_ins;//声明,静态指针成员
    A(){}
public:
    static A* getIns(){
        if(m_ins==NULL){
            m_ins=new A();
        }
        return m_ins;
    }
    void test(){
      cout<<"testA\n";
    }
    ~A(){
        cout<<"~A destruction\n";
    }
};

A* A::m_ins=nullptr;//定义
int main()
{
    A* a=A::getIns();
    a->test();
    return 0;
}

输出:

cpp 复制代码
testA

需要在返回前单独添加delete A; 否则是会有内存泄漏的风险的,不过上述的例子,程序结束后,操作系统会回收。

使用new创建对象,需要开发人员手动管理。如果不执行delete,对象和分配的内存将一直存在,直到程序退出后,才由操作系统回收。

将静态指针成员改为函数内的静态变量:

cpp 复制代码
class A{
private:
    A(){}
public:
    static A& getIns(){//返回引用
        static A m_a; //  C++11 引入的线程安全的静态变量初始化
        return m_a;
    }
    static A* getIns(){
      static A m_a;
       return & m_a;
    }
};

int main()
{
    A::getIns().test();
    return 0;
}

#输出:
-> % ./Demo
testA
~A destruction

如果使用如下:

cpp 复制代码
    static A* getIns(){
        static A* m_a;
        if(m_a==nullptr){
            m_a = new A();
        }
        return m_a;
    }
main:
A::getIns()->test();

析构函数依旧不会被执行。

2.方法

还可以在内部定义GC类,GC类的析构函数专门用来delete变量。参考:单例模式的析构问题和线程安全问题 | 烫

或者根据 GCC 的 __attribute__((destructor)) 特性,在程序退出阶段(main 函数结束或 exit() 被调用时)会自动调用 _delete()_delete() 负责释放单例实例的内存。

  • 如果没有特殊需求,建议使用静态局部变量实现单例(方式 1)。这种方法最简单,并且是现代 C++ 中的推荐实践。
  • 如果需要明确控制析构时间,推荐使用 atexit() 注册析构函数(方式 4)
相关推荐
随意起个昵称5 小时前
区间dp-基础题目1(石子合并)
算法·动态规划
吞下星星的少年·-·5 小时前
线段树模板
算法
段一凡-华北理工大学6 小时前
2026 高炉炼铁智能化技术全景与演进路径~系列文章11:演进路径与行业未来
大数据·网络·人工智能·算法·工业智能体·高炉炼铁智能化
喜欢踢足球的老罗6 小时前
从移动开发转型 AI Agent 工程师:我做了一个开源学习系统
人工智能·学习
叶小鸡6 小时前
小鸡玩算法-力扣HOT100-多维动态规划
算法·leetcode·动态规划
星马梦缘6 小时前
aaaaa
数据结构·c++·算法
wuxinyan1237 小时前
工业级大模型学习之路030:Streamlit 企业级智能体前端工作台
前端·学习·streamlit·智能体
菜菜的顾清寒7 小时前
力扣HOT100(42)链表-随机链表的复制
算法·leetcode·链表
lqqjuly7 小时前
模型剪枝与稀疏化:理论、算法与可运行实现
人工智能·算法·剪枝
逻辑君8 小时前
Foresight研究报告【20260011】
人工智能·线性代数·算法·矩阵