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;  
}
相关推荐
溟洵1 小时前
【 C/C++ 算法】入门动态规划-----一维动态规划基础(以练代学式)
c语言·c++·算法
打不了嗝 ᥬ᭄1 小时前
【Linux】线程同步与互斥
linux·服务器·c++
愚润求学1 小时前
【贪心算法】day9
c++·算法·leetcode·贪心算法
lingran__2 小时前
速通ACM省铜第二天 赋源码(Adjacent XOR和Arboris Contractio)
c++·算法
zzzsde2 小时前
【c++】类和对象(4)
开发语言·c++
抓饼先生2 小时前
C++ 20 视图view笔记
linux·开发语言·c++·笔记·c++20
大可门耳2 小时前
qt调用cef的Demo,实现js与C++之间的交互细节
javascript·c++·经验分享·qt
半桔2 小时前
【STL源码剖析】二叉世界的平衡:从BST 到 AVL-tree 和 RB-tree 的插入逻辑
java·数据结构·c++·算法·set·map
R_.L3 小时前
【项目】 :C++ - 仿mudou库one thread one loop式并发服务器实现(代码实现)
服务器·开发语言·c++
R_.L3 小时前
【项目】 :C++ - 仿mudou库one thread one loop式并发服务器实现(模块划分)
服务器·c++