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释放时,才能被释放。
相关推荐
std::allocator 是 C++标准库中提供的默认分配器,他的特点就在于我们在 使用 new 来申请内存构造新对象的时候,势必要调用类对象的默认构造函数 而使用 std::allocator 则可以将内存分配和对象的构造这两部分...
OOA、OOD与UML基础 Rose如何介入软件开发的全过程 案例:编写一个自己的简化版WinZip 案例:设计自己的事件驱动系统 案例:将缓冲池思想应用于数据集 案例:三层杂志社管理软件系统设计 159 页
OOA、OOD与UML基础 Rose如何介入软件开发的全过程 案例:编写一个自己的简化版WinZip 案例:设计自己的事件驱动系统 案例:将缓冲池思想应用于数据集 案例:三层杂志社管理软件系统设计
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是一个简单,轻量,线程安全的对象池。 它还支持一次性类型的合并,管理合并对象的生存时间并在可能的情况下进行早期处理。 池实现实现了一个简单的通用接口,因此可以对其进行模拟或替换。支持平台现在; ...
标准c库大全:C++标准库介绍 疯狂代码 http://CrazyCoder.cn/ ĵ:http:/CrazyCoder.cn/VC/Article12860.html 标准库中提供了C基本设施虽然C标准库随着C标准折腾了许多年直到标准出台才正式定型但是在标准库实 现上...
1.11对象池. . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . 21 1.11.1enable_shared_from_this . . . . . . . . . . . . . . . . . . . . . . 23 1.11.2弱回调. . . . . . . . . . . . ....
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 17、...
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 省略帧指针 ...
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...
wait()是Object类的方法,对此对象调用了wait方法导致本线程放弃对象锁,进入等待锁定池,只有针对此对象发出notify方法后本线程才进入对象锁定池准备获得对象锁进入运行状态。 同步和异步,在什么情况下分别使用? ...
组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部...
对象池的好处 对象地要求 对象地配置 使用排队组件 QC限制 QC配置 QC调用 QC播放控件 使用负荷平衡 负荷平衡要求 负荷平衡配置 小结 第16章 COM与COM+安全性 何谓安全性 WindowsNT安全简介 NT验证 ...
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 ...
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 相等性比较做了详细分析,并对 equals()方法和直接使用“==”进行比较,得出引用...
组态11:non-type template parameters 031 组态:bound friend template function 032 组态:class template explicit specialization 034 1.9.2 临时对象的产生与运用 036 1.9.3 静态常数整数成员在class 内部...
wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 14、Overload...
完全可配置的pthreads池非常快 支持IPv4和IPv6 预编译器将Web存储库包含到您的代码中 生成动态和静态内容 Cookie和高级会话管理 HTML5 Websockets支持 Multipart的内容支持 完全面向对象 包括许多例子 下载并安装...