单例模式的析构学习

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)
相关推荐
ZhengEnCi2 小时前
模型训练完整流程:从数据准备到模型上线的 10 个关键步骤(全文可跑)
后端·算法
叼烟扛炮4 小时前
[Git 实战] 学习笔记:从生成 SSH 密钥到解决 TortoiseGit 推送报错全指南
linux·运维·笔记·git·学习
蒸蒸yyyyzwd5 小时前
学习笔记 八股手撕
笔记·学习
吞下星星的少年·-·6 小时前
Div.3 CF 1131A题(排序,模拟)
算法·模拟·排序
aichitang20246 小时前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码6 小时前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-7 小时前
两数之和-C++实现
c++·算法
j7~7 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
倍利福猎头公司官方账号7 小时前
大企业HR如何向猎头公司清晰传达AI岗位的技术需求?
人工智能·算法·机器人·求职招聘·业界资讯