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

话不多说,直接上代码:
- #include
 - #include
 - #include
 - #include
 - #include
 - #include
 - #include
 - #include
 - struct A {
 - A(std::string s) { str_ = std::move(s); }
 - void print() { std::cout << str_ << std::endl; }
 - std::string str_;
 - };
 - template
 > - class ObjectPool {
 - public:
 - ObjectPool() = default;
 - ~ObjectPool() {
 - assert(freeObjects_.size() == kInitChunkSize * (std::pow(2, pool_.size()) - 1));
 - size_t chunkSize{kInitChunkSize};
 - for (auto* chunk : pool_) {
 - allocator_.deallocate(chunk, chunkSize);
 - chunkSize *= 2;
 - }
 - pool_.clear();
 - }
 - template
 - std::shared_ptr
 acquireObject(Args... args) { - if (freeObjects_.empty()) {
 - addChunk();
 - }
 - T* object{freeObjects_.back()};
 - new (object) T{std::forward
 (args)...}; - freeObjects_.pop_back();
 - return std::shared_ptr
 (object, [this](T* object) { - std::_Destroy(object);
 - freeObjects_.push_back(object);
 - });
 - }
 - private:
 - std::vector
 pool_; - std::vector
 freeObjects_; - static const size_t kInitChunkSize{5};
 - size_t newChunkSize{kInitChunkSize};
 - void addChunk() {
 - std::cout << "add Chunk \n";
 - auto* firstNewObject{allocator_.allocate(newChunkSize)};
 - pool_.push_back(firstNewObject);
 - auto oldFreeObjectSize{freeObjects_.size()};
 - freeObjects_.resize(oldFreeObjectSize + newChunkSize);
 - std::iota(std::begin(freeObjects_) + oldFreeObjectSize, std::end(freeObjects_), firstNewObject);
 - newChunkSize *= 2;
 - }
 - Allocator allocator_;
 - };
 - using APool = ObjectPool;
 - int main() {
 - APool pool;
 - for (int i = 0; i < 20; i++) {
 - auto x = pool.acquireObject(std::string("hello"));
 - x->print();
 - }
 - return 0;
 - }
 
上面的对象池实现在每次请求对象的时候都调用了构造函数和析构函数,这里大家可以根据实际情况自行选择是否必要调用。如果构造和析构成本也比较高,可以再想办法节省对应的开销。
Copyright © 2009-2022 www.wtcwzsj.com 青羊区广皓图文设计工作室(个体工商户) 版权所有 蜀ICP备19037934号