单例模式——懒汉模式(C++)

本文详细介绍了懒汉模式下单例模式的实现方法,包括线程安全的实例化过程和垃圾回收机制。通过C++代码示例,展示了如何在多线程环境下保证单例的唯一性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//懒汉模式
//优点: 第一次使用实例对象时,创建对象
//缺点: 复杂

#include <iostream>
#include <mutex>
#include <thread>
using namespace std;

class Singleton
{
public:
	static Singleton* GetInstance()  //获取实例
	{
		if (_spInstance == nullptr)  //双检查(Double-Check),保证效率和线程安全
									 //第二个以后的线程不用检查锁,提高效率
		{
			_smtx.lock();            //(多线程)第一个线程进来,并行的第二个线程进不来

			if (_spInstance == nullptr)
			{
				_spInstance = new Singleton;
			}

			_smtx.unlock();
		}

		return _spInstance;
	}

	// 实现一个内嵌垃圾回收类     
	class CGarbo
	{
	public:
		~CGarbo() {
			if (_spInstance)
			{
				delete _spInstance;
			}
		}
	};

private:
	Singleton()
	{
		cout << "Singleton()" << endl;
	}

	~Singleton()     //调CGarbo类的析构
	{
		cout << "~Singleton()" << endl;
	}

	//防拷贝
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;

	static Singleton* _spInstance;  //单例对象指针
	static mutex _smtx;             //互斥锁

	static CGarbo _scg;
};

Singleton* Singleton::_spInstance = nullptr;
mutex Singleton::_smtx;

Singleton::CGarbo Singleton::_scg;

//测试多线程
void func()
{
	//Singleton::GetInstance();                 //若不加锁,会丢掉第一个线程的返回值
	cout << Singleton::GetInstance() << endl;   //测试一下
}

int main()
{
	//多线程,两个线程并行去调func函数(用来测试)
	thread t1(func); 
	thread t2(func);

	//线程等待
	t1.join();
	t2.join();

	cout << Singleton::GetInstance() << endl;
	cout << Singleton::GetInstance() << endl;


	return 0;
}

 

### C++ 单例设计模的实现与使用 #### 实现线程安全的懒汉单例模式 为了确保实例仅被创建一次并提供全局访问点,在C++中可以通过静态成员函数来控制类对象的创建过程。下面展示了一种常见的懒加载方,即当第一次调用 `getInstance` 方法时才初始化该类的对象[^1]。 ```cpp class Singleton { private: static std::unique_ptr<Singleton> instance; // 私有化构造函数防止外部new Singleton() {} public: ~Singleton() {} // 删除拷贝构造和赋值操作符以阻止复制行为 Singleton(const Singleton&) = delete; Singleton& operator=(const Singleton&) = delete; // 获取唯一实例的方法, 使用双重检测锁机制保证多线程环境下的安全性 static Singleton* getInstance() { if (instance.get() == nullptr) { // 第一层判断减少竞争开销 std::lock_guard<std::mutex> lock(mutex_); if (!instance) { // 双重检查锁定 instance.reset(new Singleton()); } } return instance.get(); } private: static std::once_flag initFlag; // 初始化标志位 static std::mutex mutex_; // 同步互斥量用于保护临界区 }; std::unique_ptr<Singleton> Singleton::instance(nullptr); std::once_flag Singleton::initFlag; std::mutex Singleton::mutex_; ``` 这种方法不仅实现了延迟加载(Lazy Initialization),还通过双层校验加锁的方提高了并发性能,适用于高并发场景下资源的竞争管理[^2]。 #### 饿汉单例模式 如果应用程序启动之初就需要立即获取到这个唯一的实例,则可以采用饿汉的写法。这种方非常简单直观,因为实例是在定义的时候就被创建出来的,所以不存在任何同步问题[^3]。 ```cpp class Singleton { private: // 构造器私有化 Singleton() {}; public: // 禁止拷贝 Singleton(Singleton const&) = delete; void operator=(Singleton const&) = delete; // 提供全局访问接口 static Singleton& GetInstance(){ static Singleton instanse; return instanse; } }; // 客户端代码可以直接这样获得单例对象: void someFunction(){ auto &singletonObj = Singleton::GetInstance(); } ``` 此版本利用了局部静态变量特性——它们会在首次执行所在语句之前完成初始化工作,并且整个程序生命周期内只做这一次初始化动作[^4]。 #### 应用场合说明 对于大多数情况而言,推荐优先考虑基于局部静态变量特性的饿汉方案,除非确实存在明显的按需分配需求或者担心编译期就占用过多内存空间等问题才会转向更复杂的懒加载形[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值