扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
对象的池子,与线程池、内存池类似,减少频繁创建和销毁对象带来的成本(特别是消耗资源较大的对象),可用于实现对象的缓存和复用。这也算是一种设计模式。
话不多说,直接上代码:
- #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;
- }
上面的对象池实现在每次请求对象的时候都调用了构造函数和析构函数,这里大家可以根据实际情况自行选择是否必要调用。如果构造和析构成本也比较高,可以再想办法节省对应的开销。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流