栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++单例模式

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++单例模式

C++ 单例模式实现过程的演变 版本1:
class Singleton
{
	public:
		static Singleton*GetInstance()
		{
			if(_instance == nullptr)
			{
				_instance = new Singleton();
				atexit(Destructor);
			}
			return _instance;
		};
	~Singleton(){};
	private:
		static void Destructor() {
			if (nullptr != _instance) { //
				delete _instance;
				_instance = nullptr;
				}
			}
	Singleton();//构造
	Singleton(const Singleton &cpy); //拷⻉构造
	Singleton& operator=(const Singleton& other) {}
	static Singleton * _instance;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化

显而易见我们的单例模式存在线程安全的问题

版本2
class Singleton
{
	public:
		static Singleton*GetInstance()
		{
		 	std::lock_guard lock(_mutex); 
			if(_instance == nullptr)
			{
				//std::lock_guard lock(_mutex);//2.1错误
				_instance = new Singleton();
				atexit(Destructor);
			}
			return _instance;
		};
	~Singleton(){};
	private:
		static void Destructor() {
			if (nullptr != _instance) { //
				delete _instance;
				_instance = nullptr;
				}
			}
	Singleton();//构造
	Singleton(const Singleton &cpy); //拷⻉构造
	Singleton& operator=(const Singleton& other) {}
	static Singleton * _instance;
	static std::mutex _mutex;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
std::mutex Singleton::_mutex; //互斥锁初始化

在这个版本中我们引用了互斥锁,并且是lock_guard的可以自动释放的互斥锁,但是这里会存在一个性能问题,就是对于任何想要获得单例对象的线程我们都会进行加锁,但是同时只会有一个线程获得,造成大量线程堵塞,然后如果我们将互斥锁的代码写在2.1处,我们会发现这样写还是会有线程不安全的问题

版本3
class Singleton
{
	public:
		static Singleton*GetInstance()
		{
			if(_instance == nullptr)
			{
				std::lock_guard lock(_mutex);
				if(_instance ==nullptr)
				{
					_instance = new Singleton();
					atexit(Destructor);
				}
			}
			return _instance;
		};
	~Singleton(){};
	private:
		static void Destructor() {
			if (nullptr != _instance) { //
				delete _instance;
				_instance = nullptr;
				}
			}
	Singleton();//构造
	Singleton(const Singleton &cpy); //拷⻉构造
	Singleton& operator=(const Singleton& other) {}
	static Singleton * _instance;
	static std::mutex _mutex;
}
Singleton* Singleton::_instance = nullptr;//静态成员需要初始化
std::mutex Singleton::_mutex;

这个版本的单例模式虽然可以有效的避免多线程之间的问题,同时效率也是挺高的,但是在new的过程中由于cpu reorder的操作,new的执行顺序可能不是按 1. 分配内存 2. 调用构造函数 3. 返回指针 这样的顺序来执行的,有可能是先返回的指针然后调用的构造函数,这样的操作会让多线程的单例模式变得不安全

版本四
class Singleton
{
public:
	static Singleton& GetInstance() {
		static Singleton instance;
		return instance;
	}
private:
	Singleton(){}
	~Singleton() {}
	Singleton(const Singleton&) {}
	Singleton& operator=(const Singleton&) {}
};

利用静态成员变量在c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发线程将会阻塞等待初始化结束。这样可以确保单例模式只会被调用一次,该初始化方式有四大优点1. 利⽤静态局部变量特性,延迟加载;2. 利⽤静态局部变量特性,系统⾃动回收内存,⾃动调⽤析构函数;3. 静态局部变量初始化时,没有 new 操作带来的cpu指令reorder操作;4. c++11 静态局部变量初始化时,具备线程安全;

版本5- 在版本四的基础上声明模板类
template
class Singleton {
public:
static T& GetInstance() {
	static T instance; // 这⾥要初始化DesignPattern,需要调⽤DesignPattern构造函数,同时会调⽤⽗类的构造函数。
	return instance;
	}
protected:
	virtual ~Singleton() {}
	Singleton() {} // protected修饰构造函数,才能让别⼈继承
	Singleton(const Singleton&) {}
	Singleton& operator =(const Singleton&) {}
};
class DesignPattern : public Singleton {
	friend class Singleton; // friend 能让Singleton 访问到DesignPattern构造函数
public:
	~DesignPattern() {}
private:
	DesignPattern() {}
	DesignPattern(const DesignPattern&) {}
	DesignPattern& operator=(const DesignPattern&) {}
};
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/875991.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号