C++之单例模式

参考:https://www.cnblogs.com/gccbuaa/p/7268313.html

参考:https://blog.youkuaiyun.com/fchyang/article/details/81449580

单例模式是应用最多的一种设计模式,它要求每个类有且只能有一个实例对象,所以用C++设计一个单例模式的方法如下:

        1 构造函数声明为私有,这样就保证了不能随意构造一个对象。

        2 将拷贝构造函数与赋值构造函数声明为私有,并不提供他们的实现; 即禁止对象被拷贝。

        3 在类中声明一个静态的全局访问接口;

        4 声明一个静态的私有实例化指针;

#单例模式可变参数实现:保证类有且只有一个实例,并提供一个静态的全局访问接口
#pragma once

template<typename T>
class Singleton
{
public:
	template<typename...Args>	//可变参数
	static T* CreateInstance(Args&&... args)
	{
		if (m_pInstance == nullptr)
		{
			m_pInstance = new T(std::forward<Args>(args)...);
		}
		assert( m_pInstance != nullptr );
		return m_pInstance;
	}

	static T* GetInstance( void )
	{
		if (m_pInstance == nullptr)
		{
			throw std::logic_error("the instance is not init,please initialize the instance first.");
		}
		return m_pInstance;
	}

	static void DestoryInstance()
	{
		if (m_pInstance != nullptr)
		{
			delete m_pInstance;
			m_pInstance = nullptr;
		}
	}

private:
	Singleton();			//构造函数设置为私有,保证不能随意构造一个对象
	virtual ~Singleton();	//不能随意使用释放对象
	Singleton(const Singleton&);	//拷贝构造函数和赋值构造函数设置为私有,并不提供实现,即禁止对象拷贝
	Singleton& operator = (const Singleton&);

	static T* m_pInstance;		//引用性声明
};

template<class T> T* Singleton<T>::m_pInstance = nullptr;	//模板定义性声明

使用方法如下:

#include <iostream>
#include "singleton.hpp"
class Student
{
	public:
		Student(int boy = 0, int girl = 0);
		~Student(void);
		int Sum(void) { return girl_ + boy_; }
		
	private:
		int boy_;
		int girl_;
};

Student::Student(int boy, int girl)
  : boy_(boy)
  , girl_(girl)
{
}
Student::~Student(void)
{
}

int main()
{
	Singleton<Student>::CreateInstance(2,5);
	Student* pSt = nullptr;
	pSt = Singleton<Student>::GetInstance();
	
	if ( !pSt )
	{
		std::cout << "create singleton student is failed" << '\n';
		return -1;
	}

	std::cout << pSt->Sum() << '\n';
	getchar();


	Singleton<Student>::DestoryInstance();
	return 0;
}

注意:此单例模式只使用于单线程创建实例, 如果想在多线程中使用, 需要在CreateInstace()、GetInstance()和DestroyInstance()加入锁

 

上面就是一种单例类模式的C++实现,但是上述代码还有一个缺点:单例类中申请的一些资源需要手动回收,不太方便。下面提供的处理方式显然要比上面方式来的要便捷,因为它依靠内部提供的Garbo嵌套类来提供服务,当Singleton类生命周期结束时,Garbo的类对象garbo_也要销毁,它将调用析构函数,而在析构函数中又自动地释放了Singleton单例类申请的一些资源,这种实现就比较智能化。不需要手动释放资源。这是它的优势。如下所示:

template<typename T>
class Singleton
{
public:
	template<typename...Args>	//可变参数
	static T* CreateInstance(Args&&... args)
	{
		if (m_pInstance == nullptr)
		{
			m_pInstance = new T(std::forward<Args>(args)...);
		}
		assert( m_pInstance != nullptr );
		return m_pInstance;
	}

	static T* GetInstance( void )
	{
		if (m_pInstance == nullptr)
		{
			throw std::logic_error("the instance is not init,please initialize the instance first.");
		}
		return m_pInstance;
	}

public:  
    class Garbo //资源回收机制  
    {  
    public:  
        ~Garbo()  
        {  
            if( Singleton::m_pInstance != nullptr )  
            {  
                delete m_pInstance;  
				m_pInstance = nullptr;
            }  
        }  
    }; 
	
private:
	Singleton();			//构造函数设置为私有,保证不能随意构造一个对象
	virtual ~Singleton();	//不能随意使用释放对象
	Singleton(const Singleton&);	//拷贝构造函数和赋值构造函数设置为私有,并不提供实现,即禁止对象拷贝
	Singleton& operator = (const Singleton&);

	static T* m_pInstance;		//引用性声明
	static Garbo m_garbo;  		//利用对象的确定性析构
};
template<class T> T* Singleton<T>::m_pInstance = nullptr;		//模板定义性声明
template<class T> T* Singleton<T>::Garbo Singleton::m_garbo;	//定义性声明  
int main()
{
	Singleton<Student>::CreateInstance(2,5);
	Student* pSt = nullptr;
	pSt = Singleton<Student>::GetInstance();
	
	if ( !pSt )
	{
		std::cout << "create singleton student is failed" << '\n';
		return -1;
	}

	std::cout << pSt->Sum() << '\n';
	getchar();

	return 0;
}

 

 

下面提供另一种实现C++单例类模式的方法:声明一个局部静态对象(不是线程安全)

class Singleton  
{  
 public:  
    static Singleton* GetInstance();   
	void Init();
	
protected:
	Singleton();
	~Singleton();
	
public:
	int m_classID;
	std::vector<float> m_fConf;
	
private:  
    Singleton(const Singleton &other);  
    Singleton & operator=(const Singleton &other);  
	
	static Singleton* m_instance; 			// 局部静态对象
}; 

Singleton* Singleton::m_instance = nullptr;
Singleton* Singleton::GetInstance()
{
	if ( m_instance = nullptr )
	{
		static Singleton ms_Singleton;
		m_instance = &ms_Singleton;
	}
	
	return m_instance;
}

Singleton::Singleton():m_classID(0), m_fConf(std::vector<float>())
{
	cout << "Singleton "<<endl;  
}

Singleton::~Singleton()
{
	 cout << "释放内存资源"<<endl;
	 if ( m_instance != nullptr )
	 {
		 delete m_instance;
		 m_instance = nullptr;
	 }
}

这种实现方式利用了static修改函数内部的变量,当第一次调用GetInstance函数时,系统将构造一个Singleton静态对象,在后续再次调用这个函数时,系统不再执行这个语句,也就不会再构造Singleton类对象了,而直接返回m_instance本身。另外,当Singleton类对象生命周期结束时,对象会自动调用析构函数销毁,这里也就可以不用担心释放问题,需要注意的是构造函数、拷贝构造函数和赋值构造函数均私有化。

int main()  
{  
    Singleton* s1 = Singleton::GetInstance();  
    Singleton* s2 = Singleton::GetInstance(); //s1与s2是同一对象的指针
  
    return 0;  
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值