C++带模板的单例模式自动释放——内部类

实现一个模板形式的单例类,要求对于任意类型的类经过Singleton的处理之后,都能获取一个单例对象,并且可以传递任意参数(传递任意参数就是要用到可变模板参数)

单例模式

一个类只能创建一个实例,

c++ 复制代码
#include <iostream>  
 
class Singleton
{
public:
    static Singleton* getInstance()
    {
        if(nullptr == _pInstance){
            _pInstance = new Singleton();
        }
        return _pInstance;
    }
private:
    Singleton()
    {
    }
    ~Singleton()
    {
    }
private:
    static Singleton* _pInstance;
};
Singleton* Singleton::_pInstance = nullptr; 
//静态数据成员在类外初始化,对于头文件和实现文件的形式,还应将静态数据成员放在实现文件中进行初始化,避免多次定义的问题

模板形式的单例类 + 可变参数

c++ 复制代码
#include <iostream>  

template<typename T>
class Singleton
{
public:
    template <typename ...Args> //当参数个数和类型不同时,用可变参数模板
    static T* getInstance(Args ...args)
    {
        if(nullptr == _pInstance){
            _pInstance = new T(args...);
        }
        return _pInstance;
    }
private:
    Singleton()
    {
    }
    ~Singleton()
    {
    }
private:
    static T* _pInstance;
};
template <typename T>
T* Singleton<T>::_pInstance = nullptr;

单例模式自动释放------内部类

c++ 复制代码
#include <iostream>  
  
using std::cout;  
using std::endl;  
  
template<typename T>   
class Singleton  
{  
public:  
    template <typename ...Args>//参数的个数和类型不同,可变模板参数  
    static T* getInstance(Args ...args)  
    {  
        if(nullptr == _pInstance)  
        {  
            _pInstance = new T(args...); 
            //因为new出来的和singleton中传的模板类型相同,是T类型的
        }  
        return _pInstance;  
    }  
  
private:  
    class AutoRelease  
    {  
    public:  
        AutoRelease()  
        {  
            cout << "AutoRelease()" <<endl;  
        }  
  
        ~AutoRelease()  
        {  
            cout << "~AutoRelease()" <<endl;  
            if(_pInstance)  
            {  
                delete _pInstance;  
                _pInstance = nullptr;  
            }  
        }  
    };  
private:  
    Singleton()  
    {  
        cout << "Singleton()" << endl;  
    }  
    ~Singleton()  
    {  
        cout << "~Singleton()" << endl;  
    }  
private:  
    static T* _pInstance;  
    static AutoRelease _ar;  
};    
  
template <typename T>  
T* Singleton<T>::_pInstance = nullptr;  
  
template <typename T>  
typename Singleton<T>::AutoRelease Singleton<T>::_ar;  
  

# 测试
```c++

class Point  
{  
public:  
    Point(int ix = 0, int iy = 0)  
    : _ix(ix)  
    , _iy(iy)  
    {  
        cout << "Point(int ix = 0, int iy = 0)" << endl;  
    }  
  
    void print()const  
    {  
        cout << "(" << _ix  
             << "," << _iy  
             << ")" << endl;  
    }  
    ~Point()  
    {  
        cout << "~point()" <<endl;  
    }  
private:  
    int _ix;  
    int _iy;  
};
void test()  
{  
    Point *pt1 = Singleton<Point>::getInstance(1,2);  
    Point *pt2 = Singleton<Point>::getInstance(3,4);  
    pt1->print();  
    pt2->print();  
}  
  
int main(int argc, char* argv[])  
{  
    test();  
    return 0;  
}

测试结果:AutoRelease()及其析构函数没有执行 原因:_ar没有初始化为具体的值。没有写成模板的时候,_ar作为静态数据成员进行初始化。 程序结束时,生命周期结束,执行自己的析构函数的同时,带着将_pInstance销毁。此时,在main执行之前,静态数据成员已完成初始化 但有模板后,在main执行前,静态数据成员还未完成初始化。 在执行main函数、执行test后,才会将T推导成Point。在进到main之前,_ar还是抽象的,没有实例化

解决:在test执行getinstance时,就将_ar实例化(为防止_ar多次实例化,将到if语句内)

最终

c++ 复制代码
#include <iostream>  
  
using std::cout;  
using std::endl;  
  
template<typename T>   
class Singleton  
{  
public:  
    template <typename ...Args>//参数的个数和类型不同,可变模板参数  
    static T* getInstance(Args ...args)  
    {  
        if(nullptr == _pInstance)  
        {  
            _ar; 
            _pInstance = new T(args...);  
        }  
        return _pInstance;  
    }  
  
private:  
    class AutoRelease  
    {  
    public:  
        AutoRelease()  
        {  
            cout << "AutoRelease()" <<endl;  
        }  
  
        ~AutoRelease()  
        {  
            cout << "~AutoRelease()" <<endl;  
            if(_pInstance)  
            {  
                delete _pInstance;  
                _pInstance = nullptr;  
            }  
        }  
    };  
private:  
    Singleton()  
    {  
        cout << "Singleton()" << endl;  
    }  
    ~Singleton()  
    {  
        cout << "~Singleton()" << endl;  
    }  
private:  
    static T* _pInstance;  
    static AutoRelease _ar;  
};    
  
template <typename T>  
T* Singleton<T>::_pInstance = nullptr;  
  
template <typename T>  
typename Singleton<T>::AutoRelease Singleton<T>::_ar;  
  
class Point  
{  
public:  
    Point(int ix = 0, int iy = 0)  
    : _ix(ix)  
    , _iy(iy)  
    {  
        cout << "Point(int ix = 0, int iy = 0)" << endl;  
    }  
  
    void print()const  
    {  
        cout << "(" << _ix  
             << "," << _iy  
             << ")" << endl;  
    }  
    ~Point()  
    {  
        cout << "~point()" <<endl;  
    }  
private:  
    int _ix;  
    int _iy;  
};  
void test()  
{  
    Point *pt1 = Singleton<Point>::getInstance(1,2);  
    Point *pt2 = Singleton<Point>::getInstance(3,4);  
    pt1->print();  
    pt2->print();  
}  
  
int main(int argc, char* argv[])  
{  
    test();  
    return 0;  
}
相关推荐
小白|4 分钟前
cann-learning-hub:昇腾CANN社区学习中心完全指南
java·c++·算法
mirror_zAI5 分钟前
C++ 仿 QQ 聊天室项目:Qt 客户端 + epoll 服务端 + Reactor 架构(含源码)
c++·qt·架构
我不是懒洋洋14 分钟前
大语言模型(LLM)入门:从Transformer到ChatGPT
c语言·开发语言·c++
金创想15 分钟前
积木移动题目分析及解题思路——木块问题(1)
c++·算法·字符串·c·刷题·信息学奥赛·积木
BestOrNothing_201542 分钟前
C++零基础到工程实战(5.2.4):指针与引用在函数传参、返回值与效率优化中的应用
c++·指针·引用·const·函数参数
L_09071 小时前
【C++】面向对象三大特性之多态
开发语言·c++
小张成长计划..1 小时前
【C++】33:反向迭代器的实现(扩展)
c++
小明同学011 小时前
C++后端项目:统一大模型接入 SDK(五)
服务器·c++·后端·计算机网络·语言模型
Hua-Jay1 小时前
OpenCV联合C++/Qt 学习笔记(二十四)----差值法检测移动物体、稠密光流法跟踪移动物体及稀疏光流法跟踪移动物体
c++·笔记·qt·opencv·学习·计算机视觉
郭老二2 小时前
【C++】RPC:远程程序调用
c++·rpc