单例模式的析构学习

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)
相关推荐
张永清-老清18 分钟前
每周读书与学习->初识JMeter 元件(五)
学习·jmeter·性能调优·jmeter性能测试·性能分析·干货分享·每周读书与学习
低音钢琴19 分钟前
【从零开始构建性能测试体系-02】 Apache JMeter 取样器指南:从入门到精通
学习·jmeter·apache
im_AMBER33 分钟前
Web 开发 27
前端·javascript·笔记·后端·学习·web
cimeo1 小时前
【C 学习】12.2-函数补充
学习·c#
StarPrayers.2 小时前
旅行商问题(TSP)(2)(heuristics.py)(TSP 的两种贪心启发式算法实现)
前端·人工智能·python·算法·pycharm·启发式算法
微露清风2 小时前
系统性学习C++-第五讲-内存管理
java·c++·学习
爱吃橘的橘猫2 小时前
嵌入式系统与嵌入式 C 语言(2)
c语言·算法·嵌入式
235162 小时前
【LeetCode】146. LRU 缓存
java·后端·算法·leetcode·链表·缓存·职场和发展
林开落L2 小时前
线程进阶:线程池、单例模式与线程安全深度解析
linux·安全·单例模式·线程池
岁岁岁平安2 小时前
Java的双重检查锁机制(DCL)与懒加载的单例模式
java·单例模式·synchronized·