【C++】单例模式

目录

1.如何提供一个全局变量来记录函数调用次数呢?

        2.1饿汉模式

        2.2懒汉模式

                2.2.1实现一个内嵌垃圾回收类 

懒汉的另一种写法


1.如何提供一个全局变量来记录函数调用次数呢?

声明定义分离

func.h 

extern int Count ;//声明

func.cpp

#include "func.h"


int Count = 0;//定义

void func()
{
	for (int i = 10; i > 0; i--)
	{
		++Count;
	}
}

test.cpp

#include "func.h"


int main()
{
	func();
	cout << "count:" << Count << endl;
	return 0;
}

 

2.单例模式

定义:一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问(GetInstance)该实例被所有程序模块共享(所以文件都可以访问)。

2.1饿汉模式

饿汉模式:饿了随时准备吃,在调用之前就定义好了

singleton.h 

  • 单例模式只有一个对象:那么构造函数私有且声明一个静态对象(类::静态对象函数可以访问),再除了singleton.h的任意一个文件定义,再使用一个静态成员去取那个唯一的对象就达到需求;
  • 单例不可以拷贝,所有拷贝构造防拷贝;赋值重载不需要,因为赋值重载需要两个定义的对象
//饿汉模式
class GetInformation
{
public:
	static GetInformation& GetInstance()
	{
		return instance;
	}
	void Add(const int n)//对象私有+需要一个接口函数
	{
		_count += n;
	}
	int GetConut()//个数
	{
		return _count;
	}
	GetInformation(const GetInformation& instance)=delete;//单例不能拷贝,防拷贝
private:

	GetInformation(int n=0)
		:_count(n)
	{}
	int _count;

	static GetInformation instance;//类里面都是声明
};

singleton.cpp 

#include "singleton.h"
GetInformation GetInformation::instance(0);//定义,静态成员可以用类名+::访问

void func()
{
	for (int i = 10; i > 0; i--)
	{
        GetInformation::GetInstance().Add(1);
	}
}

test.cpp

#include "singleton.h"
int main()
{
	
	func();
	cout << "GetCount:" << GetInformation::GetInstance().GetConut() << endl;
	return 0;
}

执行结果

 

 2.2懒汉模式

懒汉模式:在第一次调用时才定义

singleton.h 

  • 单例模式只有一个对象:那么构造函数私有且声明一个静态对象指针(类::静态对象函数可以访问),再除了singleton.h的任意一个文件定义为nullptr,在第一次调用是new一个对象;再使用一个静态成员去取那个唯一的对象就达到需求
  • 单例不可以拷贝,所有拷贝构造防拷贝;赋值重载不需要,因为赋值重载需要两个定义的对象
//懒汉模式
class GetInformation
{
public:
	static GetInformation& GetInstance()
	{
		if (instance == nullptr)//第一次调用new一个对象处理
		{
			instance = new GetInformation;
		}
		return *instance;
	}

	void Add(const int n)
	{
		instance->_count += n;
	}

	int GetConut()
	{
		return instance->_count;
	}

	GetInformation(const GetInformation& instance) = delete;//防拷贝

	GetInformation(int n = 0)
		:_count(n)
	{}

private:

	int _count;
	static GetInformation* instance;类里面都是声明
};

singleton.cpp 

#include "singleton.h"

GetInformation* GetInformation::instance=nullptr;//定义,静态成员可以用类名+::访问

void func()
{
	for (int i = 10; i > 0; i--)
	{
		GetInformation::GetInstance().Add(1);
	}
}

test.cpp

#include "singleton.h"

int main()
{
	func();
	cout << "Getount:" << GetInformation::GetInstance().GetConut() << endl;
	return 0;
}

执行结果

2.2.1实现一个内嵌垃圾回收类 

  • 在懒汉模式中声明周期结束,只有一个对象指针,new出来的空间没有得到释放
  •  一般懒汉的单例对象,不需要回收,因为进程正常结束,资源都会还给系统,这个对象只有一个系统自动回收也没什么问题, 但是如果在单例对象释放析构时,有一些要完成的动作,比如要记录日志等等。那么可以考虑搞一个类似下面的回收类帮助去完成这个事情.

singleton.h 

  • 生命周期结束,内嵌垃圾回收类对象自动析构
//懒汉模式
class GetInformation
{
public:
	static GetInformation& GetInstance()
	{
		if (instance == nullptr)
		{
			instance = new GetInformation;
		}
		return *instance;
	} 
	GetInformation(const GetInformation& instance) = delete;

	GetInformation(int n = 0)
		:_count(n)
	{}
	// 实现一个内嵌垃圾回收类 
	class CGarbo
	{
		~CGarbo()
		{
			if (instance != nullptr)
			{
				delete instance;
			}
		}
	private:
	};
private:
	static CGarbo _CGarbo;

	int _count;
	static GetInformation* instance;//声明
};

singleton.cpp

#include "singleton.h"

GetInformation* GetInformation::instance=nullptr;//定义,静态成员可以用类名+::访问
GetInformation::CGarbo _CGarbo;//垃圾回收定义

懒汉模式和饿汉模式的优缺点

【C++】单例模式_第1张图片 

懒汉的另一种写法

  • 在C++11更推荐这种懒汉写法,它解决了懒汉的缺点
//饿汉模式
class GetInformation
{
public:
	static GetInformation& GetInstance()
	{
		// C++98 中多线程调用时,static sInst对象构造初始化并不能保证下线程安全
		// C++11 优化了这个问题,C++11中static sInst对象构造初始化是线程安全的
		static GetInformation instance;

		return instance;
	}
	void Add(const int n)
	{
		_count += n;
	}
	int GetConut()
	{
		return _count;
	}

	GetInformation(const GetInformation& instance)=delete;
private:

	GetInformation(int n=0)
		:_count(n)
	{}
	int _count;
};

你可能感兴趣的:(c++,c++,单例模式)