单例模式c++实现

        单例模式:定义一个类,这个类在实例化时只能new出一个唯一的对象,这个类叫做单例类,这个模式叫做单例模式。

        任务队列:队列中存储着一些任务函数,队列的结点类型为指针类型,指针指向函数地址。执行任务时调用函数指针指向的地址。在C++11中可以使用可调用对象代替函数指针。(可调用对象有待学习)。

       任务队列在编程时经常用到,通常以单例模式给出。单例模式是指在一个项目中,全局范围内,某个类的实例有且仅有一个,我们通过这个唯一的实例向其他模块提供数据的全局访问。也就是说单例的对象在整个项目中充当一个全局变量的角色。单例模式最典型的应用就是任务队列。全局变量之间使用不安全,使用单例时,全局变量被封装到类内作为私有成员变量,不能在类外被直接访问,可以类内提供处理函数,规定如何去操作私有成员变量, 比如在读时指定一个算法,在写时指定一个算法。总结起来就是通过单例类就可以对私有成员变量进行管理,不论是读还是写都要按照指定的模式进行,不然无法使用类提供的这个成员变量。所以单例模式类中的数据是间接被访问的,通过单例模式的类提供的成员函数访问,这样既封装了数据又保证了数据的安全性。

      单例模式创建的对象类似独生子女的性质,这里做的更彻底,直接给类做了绝育手术。

      饿汉模式:单例类定义出来后,实例对象就已经存在了。这个实例对象被初始化,new出来了内存,但是没有被使用。状态很迫切,在定义类时一并创建了单例对象,我们什么时候用,就什么时候调用静态成员函数getInstance();

单例类饿汉模式程序:

#include<iostream>
using namespace std;

//定义一个单例模式的任务队列
//移动构造函数不能创建出新的实例
//空的不带参的构造函数能够创建出新的对象实例
//拷贝构造函数可以拷贝出新的对象实例
class TaskQueue
{ 
 public:

//private:
	//写法1
	TaskQueue(const TaskQueue& t) = delete;
  TaskQueue& operator=(const TaskQueue& t) = delete;
	 static TaskQueue* getInstance()
	 {
		 return m_taskQ;
	 }

	 void print()
	 {
		 cout << "我是单例对象的一个成员函数..." << endl;
	 }

//private:
	TaskQueue() = default;//写法2
//	TaskQueue(const TaskQueue& t) = default;//C++11 default 使用这两个构造函数的默认行为
//  TaskQueue& operator=(const TaskQueue& t) = default;
 //只能通过类名访问静态成员属性或方法
	 static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;

//不要让用户在类外去调用它的构造函数(默认构造和拷贝构造)
int main()
{
	TaskQueue* taskQ = TaskQueue::getInstance();
	taskQ->print();

	system("pause");
	return 0;
}

       懒汉模式:什么时候使用这个单例对象,在使用的时候再去创建对应实例。懒汉模式相对于饿汉模式更加节省内存空间。因为饿汉模式会在内存空间中创建闲置对象。

      但是饿汉模式在多线程场景下没有线程安全问题。对于懒汉模式在多线程情况下,具有线程安全问题,即在若干个线程同时访问这个单例的实例会出问题。解决办法:1.加互斥锁,阻塞线程,让多个线程依次访问这个单例对象,就可以避免懒汉模式下多线程线程同时访问这个单例对象,创建出多个实例的这个问题。加锁顺序访问不如同时访问效率高。

懒汉模式程序:

#include<iostream>
using namespace std;

//饿汉模式
//定义一个单例模式的任务队列
//移动构造函数不能创建出新的实例
//空的不带参的构造函数能够创建出新的对象实例
//拷贝构造函数可以拷贝出新的对象实例
class TaskQueue
{
public:

	//private:
		//写法1
	TaskQueue(const TaskQueue& t) = delete;
	TaskQueue& operator=(const TaskQueue& t) = delete;
	static TaskQueue* getInstance()
	{
		if (m_taskQ == nullptr)//很重要,保证单例
		{
			m_taskQ = new TaskQueue;
		}

		return m_taskQ;
	}

	void print()
	{
		cout << "我是单例对象的一个成员函数..." << endl;
	}

	//private:
	TaskQueue() = default;//写法2
//	TaskQueue(const TaskQueue& t) = default;//C++11 default 使用这两个构造函数的默认行为
//  TaskQueue& operator=(const TaskQueue& t) = default;
 //只能通过类名访问静态成员属性或方法
	static TaskQueue* m_taskQ;
};
TaskQueue* TaskQueue::m_taskQ = nullptr;

//不要让用户在类外去调用它的构造函数(默认构造和拷贝构造)
int main()
{
	TaskQueue* taskQ = TaskQueue::getInstance();
	taskQ->print();

	system("pause");
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值