关于C++单例模式内存释放问题的一点点总结

C++学习之第九天-自动释放单例模式 编程题 1、实现单例模式的自动释放(4种方式) 1.1友元类实现单例模式的释放。 知识点: 要实现自动释放,可以考虑用一个栈对象,一个类在栈上创建一个对象,在程序执行结束后,栈对象空间被自动释放,会去调用该类的析构函数。把释放单例模式指针的代码放在该类中就可以实现自动释放。 #include <iostream> using namespace std; class AutoRelease;//1.要在单例模式中作为友元,所以先进行声明 class Singlet... 阅读详情
AI摘要

探讨C++中单例模式对象的四种释放方法:程序员手动delete、使用atexit注册函数、单例类提供释放接口及利用操作系统自动释放。分析各种方法优缺点。

目录


写在最前面

  网络上有很多关于C++单例模式的帖子,其中不乏精品之作。本篇文字在吸收了精华之余,仅作了个人的一点点总结。
  通过new出一个对象来实现的单例,不论单例是通过饿汉方式,还是懒汉方式来实现,都面临一个问题,即new出来的对象由谁释放,何时释放,怎么释放 ?简单的实现可以参考C++ 单例模式
  如果对象没有被释放,在运行期间可能会存在内存泄露问题。有人可能会说,在进程结束时,操作系统会进行必要的清理工作,包括释放进程的所有堆栈等信息,即使存在内存泄露,操作系统也会收回的;且对于单例来讲,进程运行期间仅有一个对象实例,而且该实例有可能根本就没有进行内存的申请操作,不释放实例所占内存,对进程的运行也不会造成影响。这么说好像很有道理的样子,既然操作系统会清理一切后续工作,那么我们还有必要进行内存释放工作吗?
  

正文

  闲话少叙,言归正传。作为一个非著名的程序猿,我和大多数同类一样,对代码有着不一般的情结,且有强迫症。成对的使用new和delete是程序猿们最基础的素养。这么看来,单例对象的释放必须要在代码中体现出来。

方式一:由程序猿在程序结束之前,通过调用delete来释放

很自然的,可能会有部分猿/媴们[其实就是我啦^-^]想到,把释放工作交给析构函数来处理不就行了。想法是不错,代码要怎么写呐?可能如下:

~dtor()
{
   delete instance;
}

可惜的是,一:new出来的对象,必须用与之对应的delete显示的来释放,程序并不会自动调用析构函数来析构new出来的对象;二:在delete的时候会调用析构函数,析构函数中又调用了delete,然后又调用了析构函数……这样就进入了一个无限的循环之中。

可能的代码:

int main(int argc, char ** argv)
{
    //...

    delete Singleton::get_instance();
    //...
}

valgrind检测结果
所有内存都被释放了
通过valgrind工具,我们可以看到,所有内存都被释放了。这种处理完成了任务,好像无可厚非。但是,大多数情况下,这条语句会被遗忘,如果程序中存在多个单例,也很容易将某个对象的释放操作遗漏。

方式二:通过C标准库的atexit()函数注册释放函数

  atexit()函数可以用来注册终止函数。如果打算在main()结束后执行某些操作,可以使用该函数来注册相关函数。

可能的代码:

void del_singleton_01()
{
    if (Singleton::get_instance())
    {
        delete Singleton::get_instance();
    }
}

int main(int argc, char **argv)
{
    // ...
    atexit(del_singleton_01);
    // ...
}

valgrind检测结果
所有内存都被释放了
  标准规定atexit()至少可以注册32个终止函数,如果系统中有多个单例,我们可能要注册多个函数,或者在同一个终止函数中释放所有单例对象。但是方式一中的问题依然存在。必须由程序猿/媴手工注册,且有可能遗漏某个对象。

方式三:由单例类提供释放接口

  本方式由单例类提供一个释放对象的函数,在该函数内部进行对象的释放操作。其本质与方式一并无太大差别,同样的继承了方式一的缺点。
可能的代码:

class Singleton {
public:
    // ...
    void del_object() {
        if (instance) {
            delete instance;
            instance = 0;
        }
    }
    // ...
};

int main(int argc, char ** argv)
{
    // ...
    Singleton::get_instance()->del_object();
    // ...
}

  虽然这是一种可行的释放对象方式,但是这种方式并没有明显的优点。这不是我们想要的方案。

方式四:让操作系统自动释放

  我们知道,进程结束时,静态对象的生命周期随之结束,其析构函数会被调用来释放对象。因此,我们可以利用这一特性,在单例类中声明一个内嵌类,该类的析构函数专门用来释放new出来的单例对象,并声明一个该类类型的static对象。

可能的代码:

class Singleton {
public:
    // ...
private:
    // ...
    static Singleton * instance;
    class GarbageCollector {
    public:
        ~GarbageCollector() {
            if (Singleton::instance) {
                delete Singleton::instance;
                Singleton::instance = 0;
            }
        }
    };
    static GarbageCollector gc;
};

// 定义
Singleton::GarbargeCollector Singleton::gc;
// ...

valgrind检测结果:
所有内存都被释放了
好了,我们可以像之前一样使用单例了,不需要再关心对象的释放问题。进程结束时,操作系统会帮我们去释放的。

写在最后面

  之所以要进行内存的释放,是因为在单例的实现过程中,我们使用了new来创建对象。如果在实现过程中,不使用new,而是使用静态[局部]对象的方式,就不存在释放对象的问题了。
可能的关键代码:

class Singleton {
    // ...
    static Singleton instance;
    // ...
};

// ...
Singleton Singleton::instance;
// ...

或者

class Singleton {
public:
    Singleton & get_instance();
    // ...
};

Singleton & Singleton::get_instance()
{
    static Singleton instance;
    return instance;
}

C++单例模式之析构     话说,之前虽然分别看过《大话设计模式》以及《设计模式之禅》,但是对里面的各种设计模式总是处于看过就忘的状态,唯一拿得出手的,也就是个单例模式了,窃以为已经把单例模式用得溜溜的了,然而,面试时,碰到一个问题,尴尬了。    “单利模式如何删除呢?”    好吧,尴尬的问题,尴尬的答案,下面整理一下好了。    第一反应是,会随着程序退出,进而整体释放,也就无所谓删除了,那么问题来了,假如在单... 阅读详情

相关推荐

C++ 单例模式

单例模式(Singleton Pattern)是设计模式中最简单的形式之一,其目的是使得类的一个对象成为系统中的唯一实例。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一对象的方式,可以直接访问,不需要实例化该类的对象。

青春不老,奋斗不止! 2万+

C++中单例对象的内存释放问题

C++中单例对象的内存自动释放 单例模式是一种在设计中很常用的模式,通过static函数创建一个对象,以后的所有的数据都通过该函数操作,保持数据唯一,用起来也很方便,但是有个小小的问题,就是单例对象的释放问题,一般我们都是程序退出的时候统一释放对象,但是这并不是特别完美,有时候你可能会忘记调用,然后就发生了内存泄露,当然,现代操作系统会对每个程序进行内存管理,程序销毁的时候,这个程序所创建...

lvmengzou的专栏 1543

(92页PPT)某大型集团信息化项目企业数字化转型ERP系统蓝图设计规划方案(附下载方式)

同时,外贸获利空间被严重挤压,必须从价格竞争转向品牌竞争。该方案针对某大型外贸集团在数字化时代的转型需求,提出了一套完整的ERP系统建设框架和实施路径,具有很高的专业参考价值。特别值得关注的是方案提出的"价值为先"指导思想,通过将企业价值图与信息系统建设紧密结合,确保IT投资直接支撑价值创造。同时,方案充分考虑了集团多元化、国际化的发展需求,设计了灵活可扩展的系统架构。总的来说,这份实施方案专业性强、内容全面、措施具体,既立足解决当前问题,又着眼未来发展需求,为大型集团企业的数字化转型提供了优秀范本。

AI_data_cloud的博客 1026

C++ 单例模式的自动释放

单例模式是为了确保某个类只能创建一个对象而设计的。当一个程序的某个类型只允许有一个实例的时候使用。 一般采用动态分配的方式来生成单例对象,这个时候C++程序员就需要考虑内存回收的问题了,所以为了避免在使用单例模式时忘记回收资源而造成内存泄漏的问题,在实现单例模式的时候就使其可以自动被回收。 不带自动释放的单例模式的实现与销毁 我们先来复习一下没有自动回收机制的单例模式的实现和销毁。 单例模式的实现: 将构造函数私有化 在类中定义一个静态的指向本类型的指针变量 定义一个返回值为该类的指针的静态成员函数,在类

带着你的名字的博客 1565

PX4实战指南:通过遥控器通道直连实现舵机PWM控制

本文详细介绍了如何通过PX4飞控实现遥控器通道直连控制舵机PWM输出的完整流程。从硬件准备、遥控器配对到PX4参数配置和硬件连接,提供了实战技巧和常见问题解决方案,帮助无人机爱好者快速掌握舵机控制技术。重点讲解了AUX Passthrough模式设置和PWM参数调整等关键步骤。

weixin_29195217的博客 153

Ubuntu 20.04 上 Geant4 安装避坑全记录:从源码编译到 B1 示例跑通(含数据包加速下载)

本文详细记录了在Ubuntu 20.04系统上从源码编译安装Geant4的全过程,包括环境准备、依赖安装、CMake参数解析、多线程编译优化以及数据包加速下载等关键步骤。特别针对B1示例的测试与验证提供了完整流程,帮助科研人员和学生避开常见安装陷阱,提升粒子物理模拟效率。

weixin_31220401的博客 312

c++中的单例模式

引用地址:http://www.builder.com.cn/2008/0415/815724.shtmlC++中单例模式对象的释放控制开发者在线 Builder.com.cn 更新时间:2008-04-15作者:苏林 来源:优快云本文关键词: 对象 单例模式 c++   单例模式也称为单件模式、单子模式。使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模

woyaowenzi的专栏 2050

攻克+86手机号Discord验证墙:从“无效”到“成功”的实战指南

本文提供了一份针对+86手机号在Discord注册时频繁遭遇“手机号无效”问题的实战解决指南。文章系统分析了问题根源,并分步详解了从打造纯净网络环境、尝试多种手机号格式(如+86前加0),到更换iOS等客户端设备的有效方法,旨在帮助用户成功完成Discord手机号验证。

mac99的博客 1101

关于malloc() and free()_Andy_Issta_新浪博客

Allocates memory blocks. void *malloc( size_t size );The size_ttypedef is an unsigned intsize : to allocate..Return Value: malloc returns a void pointerto the allocated space or NULL i...

issta的博客 288

Python模拟发送SOME/IP消息(Scapy模块)

SOMEIP提供服务、订阅、响应、通知等Python代码示例

liluo0815481的博客 3068

【AI黑话日日新】什么是AI Infra?

是支撑AI模型开发、训练、推理、部署与规模化运营的,是连接底层算力与上层AI应用的“数字基建”。没有高效的AI Infra,大模型训练、推理与落地都无法高效实现。

专注:太空算力、AI infra、异构调度、大模型成本工程 1098

C中堆管理——浅谈malloc,calloc,realloc函数之间的区别

<br />内存区域可以分为栈,堆,静态存储区和常量存储区。局部变量,函数形参,临时变量都是在栈上获得内存的,它们获取的方式都是由编译器自动执行的。 <br />      C 标准函数库提供了许多函数来实现对堆上内存管理,其中包括:malloc函数,free函数,calloc函数和realloc函数。使用这些函数需要包含头文件stdlib.h<br />1.   malloc函数<br />malloc函数可以从堆上获得指定字节的内存空间,其函数声明如下:<br />void * malloc(in

409

【unity知识】最新的虚拟相机Cinemachine3简单使用介绍

本文介绍了Unity中Cinemachine 3虚拟相机系统的使用方法。相比旧版本,新版功能更强大且参数分类更直观。文章详细讲解了摄像机镜头参数、旋转控制(包括None、目标跟随、样条线推拉、旋转追随等6种模式)和位置控制(跟随、样条轨道、硬锁定等5种模式)。重点演示了样条轨道摄像机的创建与配置,以及如何实现第一人称和第三人称视角。通过丰富的GIF图示,展示了各种模式的运行效果,帮助用户快速掌握Cinemachine 3的核心功能。

向宇的博客,专注php/web全栈 unity游戏开发,欢迎大家评论纠错 865

论单例模式内存释放

论单例模式内存释放 Jay_Guo关注 2017.11.26 21:37*字数 710阅读 648评论 0喜欢 1 对于C++ 项目开发者来说,单例模式可以说是最常用的也是最有效的一种设计模式,无论是单线程中的懒汉模式还是线程安全的恶汉模式,亦或是其各个变种模式,都无法避免的是在使用完成后要对该单例占用的内存进行释放,本文旨在介绍几种单例模式内存释放方式。 单例模式 在C...

jfkidear的专栏 2214

基于深度学习的茶叶等级检测识别系统:YOLOv8 + UI界面 + 数据集完整实现

随着深度学习技术的不断进步,基于计算机视觉的茶叶等级检测系统可以大大提高检测效率,提供客观一致的评估标准。本系统将利用YOLOv8进行茶叶等级的检测与识别,通过图形用户界面(UI)实现与用户的交互,提供茶叶等级分类的实时反馈。本文将详细介绍如何使用YOLOv8结合UI界面,建立一个完整的茶叶等级检测与识别系统,包括数据集的准备、模型的训练、UI的设计及完整的代码实现。本系统的目标是通过深度学习技术,结合YOLOv8模型和图形用户界面(UI),实现对茶叶等级的自动化检测与识别。

YOLO 972

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++的单例模式怎么释放内存?

经过new出一个对象来实现的单例,不论单例是经过饿汉方式,仍是懒汉方式来实现,都面临一个问题,即new出来的对象由谁释放,什么时候释放,怎么释放 ?

Jason_Lee155的博客 1736

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

C++基础之单例模式自动释放

前言一、友元形式二、内部类加静态数据成员形式三、atexit形式四、pthread_once形式 前言 个人学习笔记        之前的介绍过关于单例模式的例子,其中对象是由_pInstance指针来保存,通过new创建的对象并没有进行释放,是因为单例模式之后没有其他代码需要执行,程序会立马结束,操作系统会自行回收相关资源,但对于后面有相关代码需要执行的程序来说,这种操作就会造成内存泄漏。有没有什么方式可以让对象自动释放?这样既可.

u012344185的博客 4132

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

c++ 单例模式

1. 什么是单例模式 单例模式(Singleton Pattern,也称为单件模式),使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。 定义一个单例类: 私有化它的构造函数,以防止外界创建单例类的对象; 使用类的私有静态指针变量指向类的唯一实例; 使用一个公有的静态方法获取该实例。 2. 懒汉版(Lazy Singleton) 教学版,即懒汉版(Lazy Singleton):单例实例在第一次被使用时才进行初始化,这叫做延迟初

帅的没拼音 2万+

C++ 单例模式详解

1. 什么是单例模式 单例模式(Singleton Pattern,也称为单件模式),使用最广泛的设计模式之一。其意图是保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。 定义一个单例类: 私有化它的构造函数,以防止外界创建单例类的对象; 使用类的私有静态指针变量指向类的唯一实例; 使用一个公有的静态方法获取该实例。 2. 懒汉版(Lazy Single...

大隐隐于野 1万+

C++ 单例模式:资源初始化与资源释放的详细介绍

C++ 单例模式:资源初始化与资源释放的详细介绍

深耕嵌入式领用多年, 致力于分享嵌入式领域技术! 1506

C++中的单例模式及按需释放模型(一)

关键字:C++、单例模式、友元、模板、多线程、对象生命周期   单例模式是设计模式中最简单最容易理解的模式之一,实用方便,项目设计开发中会被经常使用,但是不知道读者有没有考虑过这个问题,单例模式实例什么时候被释放,读者有兴趣可以仔细分析下,按照目前通常方法实现的单例模式都是直到系统退出的时候才释放的,甚至是有垃圾回收机制的C#上也是这样的,系统切换了功能模块还存在大量的这个模块根本不使用的单例

gogogo的专栏 6899

C++中单例模式对象的释放控制

 单例模式也称为单件模式、单子模式。使用单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。有很多地方需要这样的功能模块,如系统的日志输出等。 单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点,但这样的代码显得很不优雅。《设计模式》一书中给出了一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用

6519

单例模式 C++

懒汉,饿汉,解决内存泄漏,双检锁,原子,C++11 magic static,模板类

IT OR 考公? 2202

C++单例模式详解

起因是在程序中重复声明了一个单例模式的变量,后来程序怎么调都不对,最后发现变量是用单例模式,修改是全局的,所以决定好好梳理一下单例模式。首先,为什么要用单例模式,就是因为我们希望一个类只有唯一一个实例,并且提供一个全局的访问点。从这个描述不难看出,这个实例应该是要static来修饰的。。

见牛羊的博客 2877

C++单例模式(线程安全、内存释放)

一、懒汉模式: 即第一次调用该类实例的时候才产生一个新的该类实例,并在以后仅返回此实例。 需要用锁,来保证其线程安全性:原因:多个线程可能进入判断是否已经存在实例的if语句,从而non thread safety. 使用double-check来保证thread safety.但是如果处理大量数据时,该锁才成为严重的性能瓶颈。 1、静态成员实例的懒汉模式: class Singleton { private: static Singleton* m_instance; Sin

lijian2017的博客 1789

C++单例模式如何进行释放控制

C++单例模式如何进行释放控制 2010-01-27 10:45 佚名 优快云 字号:T | T 想要充分的掌握C++单例模式相关技术,那么就要对C++中的结构、语句、变量、函数、预处理指令、输入和输出等内容进行了解掌握。 AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验 C++单例模式也称为单件模式、单子

jfkidear的专栏 1220
上一篇: windows C/C++ 使控制台窗口全屏
下一篇: C/C++中的const
linuxwuj
博客等级 码龄16年 25粉丝 29原创
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值