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

 什么是对象池?

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

话不多说,直接上代码:

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

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

网站题目:手撸一个对象池,你学会了吗?
本文链接:http://www.shufengxianlan.com/qtweb/news5/337355.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联