我的编程空间,编程开发者的网络收藏夹
学习永远不晚

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

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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

单例模式是为了确保某个类只能创建一个对象而设计的。当一个程序的某个类型只允许有一个实例的时候使用。

一般采用动态分配的方式来生成单例对象,这个时候C++程序员就需要考虑内存回收的问题了,所以为了避免在使用单例模式时忘记回收资源而造成内存泄漏的问题,在实现单例模式的时候就使其可以自动被回收。

不带自动释放的单例模式的实现与销毁

我们先来复习一下没有自动回收机制的单例模式的实现和销毁。

单例模式的实现:

  • 将构造函数私有化
  • 在类中定义一个静态的指向本类型的指针变量
  • 定义一个返回值为该类的指针的静态成员函数,在类的外部调用该函数,生成单例对象。

单例模式的销毁:

不能在析构函数中释放那个指向本类型的指针变量
需要用静态的成员函数回收指向本类型的指针变量,然后在类的外部调用该成员函数来销毁该单例对象。

单例模式的自动释放

主要思想是,利用C++栈对象消亡是会自动回收的特点,来自动回收分配在堆上的单例对象,可以通过四种方法:友元类、内部类+静态数据成员、atexit()函数、pthread_once()+atexit()来实现

废话不多说,直接上代码。

1.借助友元类


//利用友元类,实现单例模式的自动释放

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;
using std::cin;

class AutoRelease;

class Singleton{
    //单例模式的类
public:
    static Singleton *getInstance();//返回单例指针

private:
    friend class AutoRelease;
    Singleton();  //构造函数和析构函数都得是private
    ~Singleton();
    static Singleton *_pInstance;
};

Singleton *Singleton::getInstance(){
    if(_pInstance == nullptr){
        _pInstance = new Singleton();
    }
    return _pInstance;
}

Singleton::Singleton()
{
    cout << "Singleton()" << endl;
}

Singleton::~Singleton(){
    cout << "~Singleton()" << endl;
}

class AutoRelease{
    //用来实现单例的自动释放的类
    //应该保存在栈上,程序结束时自动回收单例的资源
public:
    AutoRelease(){
        cout << "AutoRelease()" << endl;
    }
    ~AutoRelease(){
        cout << "~AutoRelease()" << endl;
        if(Singleton::_pInstance == nullptr){
            return;
        }
        delete Singleton::_pInstance;
        Singleton::_pInstance = nullptr;
    }
};

Singleton *Singleton::_pInstance = nullptr;  //饱汉模式

int main()
{
    Singleton *s1 = Singleton::getInstance();
    Singleton *s2 = Singleton::getInstance();
    AutoRelease at;
    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    s1 = nullptr;
    s2 = nullptr;
    return 0;
}

2.借助内部类和静态数据成员


//利用内部类,实现单例模式的自动释放

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;
using std::cin;

class Singleton{
    //单例模式的类
public:
    static Singleton *getInstance();//返回单例指针

private:
    friend class AutoRelease;
    Singleton();  //构造函数和析构函数都得是private
    ~Singleton();
    static Singleton *_pInstance;

private:
    //应该设计为私有类,避免类外的其他成员使用
    class AutoRelease{
        //用来实现单例的自动释放的内部类
        //应该保存在栈上,程序结束时自动回收单例的资源
    public:
        AutoRelease(){
            cout << "AutoRelease()" << endl;
        }
        ~AutoRelease(){
            cout << "~AutoRelease()" << endl;
            if(Singleton::_pInstance == nullptr){
                return;
            }
            delete Singleton::_pInstance;
            Singleton::_pInstance = nullptr;
        }
    };

private:
    static AutoRelease _at;  //由于AutoRelease是private,所以对象应该放在静态区
};

Singleton *Singleton::getInstance(){
    if(_pInstance == nullptr){
        _pInstance = new Singleton();
    }
    return _pInstance;
}

Singleton::Singleton()
{
    cout << "Singleton()" << endl;
}

Singleton::~Singleton(){
    cout << "~Singleton()" << endl;
}



//饱汉模式多线程时不安全,需要使用饿汉模式,在程序跑起来前就生成单例对象
Singleton *Singleton::_pInstance = Singleton::getInstance();//饿汉模式
Singleton::AutoRelease Singleton::_at;

int main()
{
    Singleton *s1 = Singleton::getInstance();
    Singleton *s2 = Singleton::getInstance();
    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    s1 = nullptr;
    s2 = nullptr;
    return 0;
}

3.借助atexit()函数


//利用atexit函数,实现单例模式的自动释放

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;
using std::cin;

class Singleton{
    //单例模式的类
public:
    static Singleton *getInstance();//返回单例指针
    static void destroy();

private:
    friend class AutoRelease;
    Singleton();  //构造函数和析构函数都得是private
    ~Singleton();
    static Singleton *_pInstance;
};

Singleton *Singleton::getInstance(){
    if(_pInstance == nullptr){
        _pInstance = new Singleton();
        //注册destroy函数,在进程结束的时候执行,从而自动回收单例
        atexit(Singleton::destroy);
    }
    return _pInstance;
}

void Singleton::destroy(){
    if(Singleton::_pInstance == nullptr){
        return;
    }
    delete Singleton::_pInstance;
    Singleton::_pInstance = nullptr;
}

Singleton::Singleton()
{
    cout << "Singleton()" << endl;
}

Singleton::~Singleton(){
    cout << "~Singleton()" << endl;
}

//为了保证多线程情况下的安全性,使用饿汉模式
Singleton *Singleton::_pInstance = Singleton::getInstance();  //饿汉模式

int main()
{
    Singleton *s1 = Singleton::getInstance();
    Singleton *s2 = Singleton::getInstance();
    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    s1 = nullptr;
    s2 = nullptr;
    return 0;
}

4.借助pthread_once和atexit函数


//利用pthread_once和atexit函数,实现单例模式的自动释放

#include <stdio.h>
#include <iostream>

using std::cout;
using std::endl;
using std::cin;

class Singleton{
    //单例模式的类
public:
    static void init();
    static Singleton *getInstance();//返回单例指针
    static void destroy();

private:
    friend class AutoRelease;
    Singleton();  //构造函数和析构函数都得是private
    ~Singleton();
    static pthread_once_t _once;
    static Singleton *_pInstance;
};

void Singleton::init(){
    //初始化单例,注册回收函数
    if(_pInstance == nullptr){
        _pInstance = new Singleton();
        atexit(Singleton::destroy);
    }
}

Singleton *Singleton::getInstance(){
    //执行pthread_once,保证在多线程的情况下创建单例对象的安全性
    pthread_once(&_once, init);

    return _pInstance;
}

void Singleton::destroy(){
    if(Singleton::_pInstance == nullptr){
        return;
    }
    delete Singleton::_pInstance;
    Singleton::_pInstance = nullptr;
}

Singleton::Singleton()
{
    cout << "Singleton()" << endl;
}

Singleton::~Singleton(){
    cout << "~Singleton()" << endl;
}

//由于已经使用了pthread_once来保证安全性,所以使用饱汉模式即可
Singleton *Singleton::_pInstance = nullptr;

pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;

int main()
{
    Singleton *s1 = Singleton::getInstance();
    Singleton *s2 = Singleton::getInstance();
    printf("s1 = %p\n", s1);
    printf("s2 = %p\n", s2);
    s1 = nullptr;
    s2 = nullptr;
    return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

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

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++单例模式怎么进行释放控制

这篇文章主要介绍“C++单例模式怎么进行释放控制”,在日常操作中,相信很多人在C++单例模式怎么进行释放控制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++单例模式怎么进行释放控制”的疑惑有所帮助!接下来
2023-06-17

C++怎么实现单例模式

本篇内容介绍了“C++怎么实现单例模式”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!多线程环境下的单例模式Instance方法是这样实现的:
2023-06-19

c++单例模式的实现方式有哪些

在C++中,可以通过以下几种方式来实现单例模式:饿汉式单例模式(Eager Initialization):在类定义中静态地创建一个单例对象,保证了在程序运行期间只会创建一个实例。这种方式的缺点是无法进行延迟加载,即使程序不需要使用该单例
c++单例模式的实现方式有哪些
2024-02-29

C++单例模式的懒汉模式和饿汉模式怎么实现

本文小编为大家详细介绍“C++单例模式的懒汉模式和饿汉模式怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“C++单例模式的懒汉模式和饿汉模式怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。懒汉模式懒
2023-06-29

C++中有哪些实现单例模式的方式

这篇文章将为大家详细讲解有关C++中有哪些实现单例模式的方式,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。C++单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点,但
2023-06-17

C++实现单例模式的方法是什么

这篇文章将为大家详细讲解有关C++实现单例模式的方法是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。饿汉模式类实例化就会占用内存,浪费资源,效率高,不存在线程安全问题。class Sin
2023-06-22

C++单例模式实现线程池的示例代码

这篇文章主要为大家详细介绍了如何利用C++单例模式简单实现一个线程池,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
2023-05-16

C++实现单例模式日志输出详解

这篇文章主要为大家详细介绍了C++中单例模式的相关知识,并给出单例模式日志实现,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
2023-05-17

在Java中,如何实现单例模式?有哪些实现方式?(请列举并解释Java中实现单例模式的几种常见方法。)

Java中单例模式确保一个类只有一个实例,用于控制资源访问、保持状态或提供全局访问点。实现方式包括:饿汉式:加载类时创建实例(线程安全,但浪费资源)。懒汉式:需要时创建实例(节省资源,但线程不安全,需同步)。双重检查锁定:优化懒汉式,使用volatile防止指令重排序(线程安全,性能较好)。枚举单例:利用枚举天生单例性和线程安全性。静态内部类:延迟加载,利用静态内部类确保单例性。
在Java中,如何实现单例模式?有哪些实现方式?(请列举并解释Java中实现单例模式的几种常见方法。)
2024-04-02

Java的单例模式如何实现

这篇文章主要介绍“Java的单例模式如何实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java的单例模式如何实现”文章能帮助大家解决问题。什么是单例模式单例模式(Singleton Patter
2023-06-27

spring的单例模式如何现实

在Spring中,有多种方式来实现单例模式:默认的单例模式:Spring容器默认情况下会将所有声明为Bean的对象作为单例对象进行管理。当一个Bean被声明为单例时,在容器启动阶段会创建该Bean的实例,并且将该实例放入Spring容器的B
spring的单例模式如何现实
2024-02-29

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录