C++11应用:对象池

阅读更多

    ObjectPool.hpp:

#pragma once

#include 
#include 
#include 
#include 

using namespace std;

template 
class ObjectPool
{
	template 
	using Constructor = std::function(Args...)>;
public:
	~ObjectPool()
	{
		destructedFlag = true;
	}

	// 默认创建多少个对象
	template 
	void Init(size_t num, Args&&... args)
	{
		if (num <= 0)
		{
			throw std::logic_error("object num out of range!");
		}
		m_object_map.clear();
		auto constructName = typeid(Constructor).name(); // 不区分引用
		for (size_t i = 0; i < num; i++)
		{
			m_object_map.emplace(constructName, std::shared_ptr(new T(std::forward(args)...), [this, constructName](T* p)
			{
				// (析构函数)删除器中不直接删除对象,而是回收到对象池中,以供下一次使用
				if (!destructedFlag) // 解决内存中释放的时序造成的野指针,如果ObjectPool对象先释放,T对象后释放,则触发这里emplace会卡死
				{
					m_object_map.emplace(std::move(constructName), std::shared_ptr(p));
				}
				else {
					delete p;
				}
			}));
		}
	}
	// 从对象池中获取一个对象
	template 
	std::shared_ptr Get()
	{
		string constructName = typeid(Constructor).name();
		auto range = m_object_map.equal_range(constructName);
		for (auto it = range.first; it != range.second; ++it)
		{
			auto ptr = it->second;
			m_object_map.erase(it);
			return ptr;
		}
		return nullptr;
	}

private:
	multimap> m_object_map;
	bool destructedFlag = false;

};

    测试代码:

#include 
#include   

#include "ObjectPool.hpp"
 
using namespace std;

struct MyObj
{
	MyObj() 
	{
		cout << "MyObj construct... 0x" << hex << this << endl;
	}
	MyObj(int a)
	{
		cout << "MyObj construct:" << a << " 0x" << hex << this << endl;
	}
	MyObj(const int& a, const int& b) 
	{
		cout << "MyObj construct a:" << a << " b:" << b << " 0x" << hex << this << endl;
	}
	~MyObj()
	{
		cout << "MyObj destruct... 0x" << hex << this << endl;
	}
	void print(const string& str)
	{
		cout << "print:" << str.c_str() << endl;
	}
};
void printTest(std::shared_ptr p, const string& str)
{
	if (p != nullptr)
	{
		p->print(str);
	}
	else {
		cout << "printTest error: p is nullptr..." << endl;
	}
}

void TestObjPool() 
{
	ObjectPool pool;
	pool.Init(2); // 初始化两个对象

	// 除了下面的作用域,对象又会自动回收
	{
		auto p1 = pool.Get();
		printTest(p1, "p1...");

		auto p2 = pool.Get();
		printTest(p2, "p2...");
		cout << "---------------------" << endl;
	}

	auto p1 = pool.Get();
	auto p2 = pool.Get();
	printTest(p1, "p1");
	printTest(p2, "p2");
	cout << "===========================0" << endl;

	ObjectPool pool2;
	pool2.Init(2, 1); // 初始化两个对象,并用1来实例对应的对象构造函数
	auto p4 = pool2.Get();
	printTest(p4, "p4");
	cout << "===========================1" << endl;

	pool.Init(2, 3, 4); // 初始化两个对象,并用3和4来实例对应的对象构造函数
	auto p5 = pool.Get();
	printTest(p5, "p5");
	cout << "===========================2" << endl;
}

int main(int, char *[])
{     
	
	TestObjPool(); 

	system("pause");
	return 0;
}

    虽然同一个ObjectPool可以执行多次Init,但所有Init创建的实例,都要在该ObjectPool释放时,才能被释放。 

 

 

 

你可能感兴趣的:(C++11应用:对象池)