欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

【C++】单例模式之C++实现

程序员文章站 2022-05-06 10:25:46
单例模式的概念 只允许一个产生一个对象的类 单例模式的实现方法 1.单例类保证全局只有唯一一个自行创建的实例对象 2.单例类提供获取这个唯一实例的接口 单例模式的优缺点 优点 (1)阻止其他度对象实...

单例模式的概念

只允许一个产生一个对象的类

单例模式的实现方法

1.单例类保证全局只有唯一一个自行创建的实例对象
2.单例类提供获取这个唯一实例的接口

单例模式的优缺点

优点

(1)阻止其他度对象实例化自己的副本,保证所有访问唯一性
(2)类控制了实例化的过程,所以可以灵活的更改实例化的过程

缺点

(1)每次都需要检查是否对象已经生成,造成些微的开销
(2)使用单例对象时,开发人员可能会意外发现自己无法实例化该类

单例模式的分类

懒汉模式(适用于各种场景)

在需要的时候创建对象
懒汉模式需要加入synchronized才可以保证线程安全

饿汉模式(在某些场景下受到限制)

在main函数开始的时候即创建对象

饿汉模式是线程安全的

代码实现

懒汉模式的实现

普通版本

class singleton
{
public:
	static singleton* getinstance()//获取对象实例的唯一接口
	{
		if (_inst == null)
		{
			_inst = new singleton;
		}
		return _inst;
	}

	void print()
	{
		cout << "singleton : " << _a << endl;
	}

private:
	singleton()//防止构造函数创建对象
		:_a(0)
	{}

	singleton& operator=(const singleton&) = delete;
	singleton(const singleton&) = delete;

	int _a;
	static singleton* _inst;//指向实例化的指针定义成静态成员
};

singleton* singleton::_inst = null;

线程安全版本

加入raii机制,避免死锁的出现

class singleton
{
public:
	static singleton* getinstance()//获取对象实例的唯一接口
	{
		if (null == _inst)//只有在创建实例的时候才进行加锁提高效率
		{
			lock_guardlock(_mtx);
			if (_inst == null)
			{
				_inst = new singleton;
			}
		}
		return _inst;
	}

	void print()
	{
		cout << "singleton : " << _a << endl;
	}

private:
	singleton()//防止构造函数创建对象
		:_a(0)
	{}

	singleton& operator=(const singleton&) = delete;
	singleton(const singleton&) = delete;

	int _a;
	static singleton* _inst;//指向实例化的指针定义成静态成员
	static mutex _mtx;//保证安全的互斥锁
};

singleton* singleton::_inst = null;
mutex singleton::_mtx;

内存栅栏技术&单例对象的释放

添加双检查机制来提高效率

添加内存栅栏技术来防止由于提升效率而打乱执行的顺序

对单例模式的释放,下面这种方法是有问题的

最好是调用atexit回调机制,在main函数结束完毕后再进行释放

class singleton
{
public:
	static singleton* getinstance()//获取对象实例的唯一接口
	{
		if (null == _inst)//只有在创建实例的时候才进行加锁提高效率
		{
			lock_guardlock(_mtx);

			if (_inst == null)
			{
				singleton* tmp = new singleton;
				memorybarrier();//内存栅栏技术
				_inst = tmp;
			}
		}
		return _inst;
	}

	void print()
	{
		cout << "singleton : " << _inst << endl;
	}

	static void dellinstance()
	{
		lock_guardlock(_mtx);

		if (_inst)
		{
			cout << "delete " << endl;
			delete _inst;
			_inst = null;
		}
	}

private:
	singleton()//防止构造函数创建对象
		:_a(0)
	{}

	singleton& operator=(const singleton&) = delete;
	singleton(const singleton&) = delete;

	int _a;
	static singleton* _inst;//指向实例化的指针定义成静态成员
	static mutex _mtx;//保证安全的互斥锁
};

singleton* singleton::_inst = null;
mutex singleton::_mtx;

饿汉模式的实现

简洁,高效,不用加锁

但是在特定情况下会出现问题

实现方法1

class singleton
{
public:
	static singleton& getinstance()
	{
		assert(_inst);
		return *_inst;
	}

	void print()
	{
		cout << "singleton : " << _inst << endl;
	}
private:
	singleton()
		:_a(0)
	{}

	int _a;
	singleton& operator=(const singleton&) = delete;
	singleton(const singleton&) = delete;

	static singleton* _inst;
};

singleton* singleton::_inst = new singleton;

实现方法2

class singleton
{
public:
	static singleton& getinstance()
	{
		static single _inst;
		return *_inst;
	}

	void print()
	{
		cout << "singleton : " << _inst << endl;
	}
private:
	singleton()
		:_a(0)
	{}

	int _a;
	singleton& operator=(const singleton&) = delete;
	singleton(const singleton&) = delete;

	static singleton* _inst;
};

singleton* singleton::_inst = null;