手撸一个对象池,你学会了吗?

开发 前端
对象的池子,与线程池、内存池类似,减少频繁创建和销毁对象带来的成本(特别是消耗资源较大的对象),可用于实现对象的缓存和复用。这也算是一种设计模式。

[[427113]]

 什么是对象池?

对象的池子,与线程池、内存池类似,减少频繁创建和销毁对象带来的成本(特别是消耗资源较大的对象),可用于实现对象的缓存和复用。这也算是一种设计模式。

话不多说,直接上代码:

  1. #include <algorithm> 
  2. #include <cassert> 
  3. #include <cmath> 
  4. #include <complex> 
  5. #include <iostream> 
  6. #include <memory> 
  7. #include <numeric
  8. #include <vector> 
  9.  
  10. struct A { 
  11.     A(std::string s) { str_ = std::move(s); } 
  12.  
  13.     void print() { std::cout << str_ << std::endl; } 
  14.  
  15.     std::string str_; 
  16. }; 
  17.  
  18. template <typename T, typename Allocator = std::allocator<T>> 
  19. class ObjectPool { 
  20.    public
  21.     ObjectPool() = default
  22.     ~ObjectPool() { 
  23.         assert(freeObjects_.size() == kInitChunkSize * (std::pow(2, pool_.size()) - 1)); 
  24.  
  25.         size_t chunkSize{kInitChunkSize}; 
  26.         for (auto* chunk : pool_) { 
  27.             allocator_.deallocate(chunk, chunkSize); 
  28.             chunkSize *= 2; 
  29.         } 
  30.         pool_.clear(); 
  31.     } 
  32.  
  33.     template <typename... Args> 
  34.     std::shared_ptr<T> acquireObject(Args... args) { 
  35.         if (freeObjects_.empty()) { 
  36.             addChunk(); 
  37.         } 
  38.  
  39.         T* object{freeObjects_.back()}; 
  40.  
  41.         new (object) T{std::forward<Args>(args)...}; 
  42.  
  43.         freeObjects_.pop_back(); 
  44.  
  45.         return std::shared_ptr<T>(object, [this](T* object) { 
  46.             std::_Destroy(object); 
  47.             freeObjects_.push_back(object); 
  48.         }); 
  49.     } 
  50.  
  51.    private: 
  52.     std::vector<T*> pool_; 
  53.  
  54.     std::vector<T*> freeObjects_; 
  55.  
  56.     static const size_t kInitChunkSize{5}; 
  57.  
  58.     size_t newChunkSize{kInitChunkSize}; 
  59.  
  60.     void addChunk() { 
  61.         std::cout << "add Chunk \n"
  62.  
  63.         auto* firstNewObject{allocator_.allocate(newChunkSize)}; 
  64.         pool_.push_back(firstNewObject); 
  65.  
  66.         auto oldFreeObjectSize{freeObjects_.size()}; 
  67.         freeObjects_.resize(oldFreeObjectSize + newChunkSize); 
  68.         std::iota(std::begin(freeObjects_) + oldFreeObjectSize, std::end(freeObjects_), firstNewObject); 
  69.  
  70.         newChunkSize *= 2; 
  71.     } 
  72.  
  73.     Allocator allocator_; 
  74. }; 
  75.  
  76. using APool = ObjectPool<A>; 
  77.  
  78. int main() { 
  79.     APool pool; 
  80.     for (int i = 0; i < 20; i++) { 
  81.         auto x = pool.acquireObject(std::string("hello")); 
  82.         x->print(); 
  83.     } 
  84.     return 0; 

上面的对象池实现在每次请求对象的时候都调用了构造函数和析构函数,这里大家可以根据实际情况自行选择是否必要调用。如果构造和析构成本也比较高,可以再想办法节省对应的开销。

 

责任编辑:武晓燕 来源: 程序喵大人
相关推荐

2022-02-08 09:09:45

智能指针C++

2023-03-26 22:02:53

APMPR监控

2024-06-21 08:15:25

2024-06-19 09:47:21

2023-09-19 08:03:50

rebase​merge

2024-04-01 08:13:59

排行榜MySQL持久化

2023-04-27 08:42:50

效果

2024-01-05 07:46:15

JS克隆对象JSON

2024-01-19 08:25:38

死锁Java通信

2024-02-04 00:00:00

Effect数据组件

2023-01-10 08:43:15

定义DDD架构

2023-07-26 13:11:21

ChatGPT平台工具

2023-11-27 07:33:55

2021-10-27 06:49:34

线程池Core函数

2024-09-26 09:10:08

2023-10-26 07:15:46

2024-01-02 12:05:26

Java并发编程

2023-08-01 12:51:18

WebGPT机器学习模型

2023-07-10 07:17:29

无效化空窗口

2022-04-26 10:47:53

分配权限vuejs
点赞
收藏

51CTO技术栈公众号