`

C++11应用:对象池

 
阅读更多

    ObjectPool.hpp:

#pragma once

#include <string>
#include <memory>
#include <functional>
#include <map>

using namespace std;

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

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

};

    测试代码:

#include <iostream>
#include <string>  

#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<MyObj> p, const string& str)
{
	if (p != nullptr)
	{
		p->print(str);
	}
	else {
		cout << "printTest error: p is nullptr..." << endl;
	}
}

void TestObjPool() 
{
	ObjectPool<MyObj> 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<MyObj> pool2;
	pool2.Init(2, 1); // 初始化两个对象,并用1来实例对应的对象构造函数
	auto p4 = pool2.Get<int>();
	printTest(p4, "p4");
	cout << "===========================1" << endl;

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

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

	system("pause");
	return 0;
}

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

 

 

 

分享到:
评论

相关推荐

    c++高性能内存池.rar

    std::allocator 是 C++标准库中提供的默认分配器,他的特点就在于我们在 使用 new 来申请内存构造新对象的时候,势必要调用类对象的默认构造函数 而使用 std::allocator 则可以将内存分配和对象的构造这两部分...

    C++ 面向对象实践

    OOA、OOD与UML基础 Rose如何介入软件开发的全过程 案例:编写一个自己的简化版WinZip 案例:设计自己的事件驱动系统 案例:将缓冲池思想应用于数据集 案例:三层杂志社管理软件系统设计 159 页

    面向对象技术的C++ OOD实践

    OOA、OOD与UML基础 Rose如何介入软件开发的全过程 案例:编写一个自己的简化版WinZip 案例:设计自己的事件驱动系统 案例:将缓冲池思想应用于数据集 案例:三层杂志社管理软件系统设计

    Visual C++实践与提高-COM和COM+篇『PDF』

    12.3.4 COM+对象池 12.4 COM+新增系统服务 12.4.1 COM+队列组件 12.4.2 COM+事件模型 12.4.3 负载平衡 12.3.4 内存数据库 小结 第13章 COM+应用开发 13.1 最简单的COM+组件——例程Step1 13.1.1 创建一个最...

    PoolSharp:PoolSharp是一个简单,轻量,线程安全的对象池

    PoolSharp是一个简单,轻量,线程安全的对象池。 它还支持一次性类型的合并,管理合并对象的生存时间并在可能的情况下进行早期处理。 池实现实现了一个简单的通用接口,因此可以对其进行模拟或替换。支持平台现在; ...

    C++标准库介绍.pdf

    标准c库大全:C++标准库介绍 疯狂代码 http://CrazyCoder.cn/ ĵ:http:/CrazyCoder.cn/VC/Article12860.html  标准库中提供了C基本设施虽然C标准库随着C标准折腾了许多年直到标准出台才正式定型但是在标准库实 现上...

    Linux多线程服务端编程:使用muduo C++网络库

    1.11对象池. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . 21 1.11.1enable_shared_from_this . . . . . . . . . . . . . . . . . . . . . . 23 1.11.2弱回调. . . . . . . . . . . . ....

    超级有影响力霸气的Java面试题大全文档

    wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 17、...

    McGraw C++程序调试实用手册

    2.2.3 字符串池 2.2.4 使用register键字 2.2.5 常量和复制的传播 2.2.6 消除死代码和死存储 2.2.7 删除冗余于表达式 2.2.8 优化循环 2.2.9 降低强度 2.2.10 inline键字的使用 2.2.11 省略帧指针 ...

    iPhone应用开发从入门到精通代码

    C语言与C++混用975.4 本章小结985.5 本章练习98第6章 iPhone程序的设计模式996.1 MVC模式996.2 对象共享模式1016.3 目标和动作模式1046.4 通告模式1056.5 归档模式1076.6 子视图模式1086.7 委托模式1106.8...

    java面试题

    wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。 同步和异步,在什么情况下分别使用? ...

    STL 源码剖析(侯捷先生译著)

    组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部...

    COM与COM+从入门到精通(pdf版本,含源码)

    对象池的好处 对象地要求 对象地配置 使用排队组件 QC限制 QC配置 QC调用 QC播放控件 使用负荷平衡 负荷平衡要求 负荷平衡配置 小结 第16章 COM与COM+安全性 何谓安全性 WindowsNT安全简介 NT验证 ...

    ASP3《高级编程》(第一部分)

    8.3.6 连接缓冲池 257 8.4 记录集 258 8.4.1 光标 258 8.4.2 锁定 260 8.4.3 创建记录集 261 8.4.4 过滤记录集 265 8.4.5 查找记录 266 8.4.6 修改记录 267 8.5 管理错误 269 8.5.1 Errors集合 269 8.5.2 ...

    ASP3《高级编程》(第二部分)

    8.3.6 连接缓冲池 257 8.4 记录集 258 8.4.1 光标 258 8.4.2 锁定 260 8.4.3 创建记录集 261 8.4.4 过滤记录集 265 8.4.5 查找记录 266 8.4.6 修改记录 267 8.5 管理错误 269 8.5.1 Errors集合 269 8.5.2 ...

    Java中关于字符串的若干问题分析.pdf

    通过用不同的方法对字符串初始化,结合反编译分析,得到初始化方法对程序结果的影响以及常量池的分配原则。 在此基础上,对 Java 相等性比较做了详细分析,并对 equals()方法和直接使用“==”进行比较,得出引用...

    STL源码剖析.pdg

    组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部...

    java 面试题 总结

    wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、Overload...

    libnavajo:C ++ API

    完全可配置的pthreads池非常快 支持IPv4和IPv6 预编译器将Web存储库包含到您的代码中 生成动态和静态内容 Cookie和高级会话管理 HTML5 Websockets支持 Multipart的内容支持 完全面向对象 包括许多例子 下载并安装...

Global site tag (gtag.js) - Google Analytics