【cpp--->特殊类设计】

一、不能被拷贝的类

#include<iostream>
using namespace std; 
class heaponly
{
public:
	heaponly() {}
	heaponly(const heaponly& ho) = delete;
private:
	int _x=0;
};

二、只能在堆上创建对象的类

方法1

#include<iostream>
using namespace std; 
class heaponly
{
public:
	void Destroy()
	{
		delete this;
	}
private:
	//析构私有化
	~heaponly() {}
private:
	int _x=0;
};
int main()
{
	heaponly* d = new heaponly;
	//显示调用释放对象空间
	d->Destroy();
	return 0;
}

方法2

#include<iostream>
using namespace std; 
class heaponly
{
public:
	static heaponly* Create()
	{
		heaponly* pj=new heaponly;
		return pj;
	}
private:
	heaponly() { cout << "stackonly()" << endl; }
	~heaponly(){}
	heaponly(const stackonly& ho) = delete;
	heaponly& opertor=(const stackonly& ho) = delete;
	int _x=0;
};
int main()
{
	heaponly* s1 = heaponly::Create();
	return 0;
}

三、只能在栈上创建对象的类

将构造私有,创建静态成员函数,其返回值是栈上开辟的对象.但是这样无法阻止静态区开辟空间的对象接收对象的值.

#include<iostream>
using namespace std; 
class stackonly
{
public:
	static stackonly Create()
	{
		return stackonly();
	}
	//右值引用
	stackonly(const stackonly&& ho) { _x = ho._x; }
private:
	stackonly() { cout << "stackonly()" << endl; }
	stackonly(const stackonly& ho) = delete;
	int _x=0;
};
int main()
{
	stackonly s1 = stackonly::Create();
	//静态区创建对象无法彻底组织
	static stackonly s2 = stackonly::Create();
	cout << typeid(s2).name() << endl;
	return 0;
}

四、只能创建一个对象的类(单例模式)

1.饿汉模式

首先将构造私有化,防止随意构造对象,定义静态成员对象指针,没使用的时候就初始化一个对象.使用时通过调用静态成员返回值静态成员对象指针,用这个指针调用类的成员函数使用类.

#include<iostream>
using namespace std;
class Singleton
{
public:
	static Singleton* GetInstance()
	{
		return _ins;
	}
	void Add(const string& str)
	{
		_mtx.lock();
		_v.push_back(str);
		_mtx.unlock();
	}
	void Print()
	{
		_mtx.lock();
		for (auto& e : _v)
		{
			cout << e << endl;
		}
		cout << endl;
		_mtx.unlock();
	}
private:
	// 限制类外面随意创建对象
	Singleton()
	{}
private:
	mutex _mtx;
	vector<string> _v;
	static Singleton* _ins;
};
//在类外面定义,任然可以使用类的私有成员--构造函数
Singleton* Singleton::_ins = new Singleton;

2.懒汉模式

懒汉模式相比饿汉模式更加可控,对于对象的创建来说,而且如果对象占内存比较大,一开始运行就创建对象会拖慢程序的运行.懒汉模式实现思想是创建一个静态全局对象变量,初始化为空,设置静态全局成员函数,调用这个函数时如果对象为空,就实例化一个对象并返回对象指针,如果不为空直接返回对象指针.这个对象指针可以调用类的成员函数,实现对类的成员变量的操控.

单例模式下的类对象一般为全局对象,一般不需要显示调用释放资源,调用资源释放函数可以直接释放资源,也可以实现一个内部类,实例化一个此类的静态全局对象,这个类的析构调用单例对象的资源释放函数,当内部类的对象析构时,会将单例对象资源释放.

#include<iostream>
#include<thread>
#include<vector>
#include<string>
#include<mutex>
#include<time.h>
using namespace std;
namespace kk
{
	class singleton//单例
	{
	public:
		//如果没有实例化调用create就是实例化,如果实例化了在调用
		//就是获取对象指针.
		static singleton* getInstance()
		{
			//如果不为空则直接返回,避免冗余的加锁解锁
			if (_instance == nullptr)
			{
				//锁可能被另一个线程申请,而后_instance被初始化.
				_mtx.lock();
				if (_instance == nullptr)
				{
					_instance = new singleton;
				}
				_mtx.unlock();
			}
			return _instance;
		}
		void add(const string& str)
		{
			//全局只有一个_v所以要加锁
			_mtx.lock();
			_v.push_back(str);
			_mtx.unlock();
		}
		void print()
		{
			_mtx.lock();
			for (auto x : _v)
			{
				cout << x << endl;
			}
			_mtx.unlock();
		}
		//显示调用释放资源
		void delInstance()
		{
			_mtx.lock();
			delete _instance;
			_instance = nullptr;
			_mtx.unlock();
		}
		//在程序结束的时候调用Gc的析构释放_singleton对象的资源
		class Gc
		{
		public:
			~Gc() {_instance->delInstance();}
		};
	private:
		//防止类外创建对象
		singleton() {};
		vector<string> _v;
		static singleton* _instance;//实例
		static mutex _mtx;
		static Gc _gc;
	};
	singleton* singleton::_instance = nullptr;
	mutex singleton::_mtx;
	singleton::Gc singleton::_gc;
	void test()
	{
		size_t n = 10;
		srand((time_t)time(0));
		thread t1([n]() {
			for (size_t i = 0; i < n; i++)
			{
				singleton::getInstance()->add("thread1:" + to_string(rand()));
			}
			});
		thread t2([n]() {
			for (size_t i = 0; i < n; i++)
			{
				singleton::getInstance()->add("thread2:" + to_string(rand()));
			}
			});
		t1.join();
		t2.join();
		//这里的print不能再join之前,因为print与线程并行运行时_v可能是空的.
		//当join运行结束,证明线程运行结束了,这个时候可以运行print
		singleton::getInstance()->print();
	}
}
int main()
{
	try
	{
		kk::test();
	}
	catch (...)
	{
		cout << "位置异常" << endl;
	}
	return 0;
}

懒汉模式对象的创建在C++11版本之后还可以利用静态变量只会被初始化一次的特性来创建.这种方法在C++11之前不是线程安全的,多线程调用次函数可能会创建多个对象.

static singleton<T>* GetInstance()
{
	static singleton<T> sl;
	return &sl;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值