C++的对象池实践

一、介绍

C++对象池是一种常用的内存管理技术,它可以提高程序的效率和性能。对象池是一种预先分配好一定数量的对象内存池,当需要使用对象时,从对象池中获取一个空闲的对象,使用完毕后再将其放回池中,以便下次使用。这样可以避免频繁的内存分配和释放,减少内存碎片,提高程序的效率和性能。

二、对象池解决什么问题

对象池通常用于需要频繁创建和销毁对象的场景,如网络编程中的连接池、线程池、对象缓存等。C++中可以使用标准库中的std::vectorstd::deque来实现对象池,也可以自己实现一个对象池,具体实现方式可以使用链表、数组等数据结构,根据实际需要进行优化。

三、 实例

一个简单的线程池

template<class T>
class SimpleObjectPool
{
public:
    using DelType = std::function<void(T*)>;

    void add(std::unique_ptr<T> t)
    {
        m_pool.push_back(std::move(t));
    }

    std::unique_ptr<T, DelType> get()
    {
        if (m_pool.empty())
        {
            throw std::logic_error("no object");
        }

        //every time add custom deleter for default unique_ptr
        std::unique_ptr<T, DelType> ptr(m_pool.back().release(), [this](T* t)
        {
            m_pool.push_back(std::unique_ptr<T>(t));    //删除函数执行的操作
        });

        m_pool.pop_back();  //删除最后一个被释放的unique_ptr
        return std::move(ptr);
    }

    bool empty() const
    {
        return m_pool.empty();
    }

    int size() const
    {
        return m_pool.size();
    }
private:
    std::vector<std::unique_ptr<T>> m_pool;
};

//测试对象
struct STA
{
    STA()
    {
        cout << "create" << endl;
    }
    STA(int i)
    {
        a = i;
        cout << "create int" << endl;
    }
    STA(const STA& other)
    {
        *this = other;
        cout << "copy" << endl;
    }
    ~STA()
    {
        cout << "delete" << endl;
    }
    int a = 0;
};

//测试代码
void testPool()
{
    SimpleObjectPool<STA> pool;
    pool.add(std::unique_ptr<STA>(new STA()));
    pool.add(std::unique_ptr<STA>(new STA()));
    {
        auto ptr = pool.get();
        pool.get();
        cout <<"pool size:"<< pool.size() << endl;
    }
    cout << "pool size:" << pool.size() << endl;
    {
        pool.get();
        pool.get();
        cout << "pool size:" << pool.size() << endl;
    }
    cout << "pool size:" << pool.size() << endl;
}

另一个demo

#include <iostream>
#include <vector>

using namespace std;

class Object {
public:
    Object() {
        cout << "Object created" << endl;
    }

    ~Object() {
        cout << "Object destroyed" << endl;
    }
};

class ObjectPool {
private:
    vector<Object*> objects;
public:
    Object* acquire() {
        if (objects.empty()) {
            return new Object;
        } 
        else {
            Object* obj = objects.back();
            objects.pop_back();
            return obj;
        }
    }

    void release(Object* obj) {
        objects.push_back(obj);
    }
};

int main() {
    ObjectPool objPool;

    // acquire an object from the pool
    Object* newObj1 = objPool.acquire();

    // acquire another object from the pool
    Object* newObj2 = objPool.acquire();

    // release the first object back to the pool
    objPool.release(newObj1);

    // acquire an object from the pool
    Object* newObj3 = objPool.acquire();

    // release the second object back to the pool
    objPool.release(newObj2);

    // release the third object back to the pool
    objPool.release(newObj3);

    return 0;
}

四、总结

对象池的优点:

    提升了t获取对象的响应速度,比如单个线程和资源连接的创建成本都比较大。
    运用对象池化技术可以显著地提升性能,尤其是当对象的初始化过程代价较大或者频率较高时。
    一定程度上减少了GC的压力。对于实时性要求较高的程序有很大的帮助
    比如说 http 链接的对象池,Redis对象池等等都使用了对象池

对象池的缺点:

设计和使用对象池容易出错, 设计上需要注意状态同步,并发环境中, 多个线程可能(同时)需要获取池中对象, 进而需要在堆数据结构上进行同步或者因为锁竞争而产生阻塞, 这是个难点, 使用上可能存在忘记归还(就像C语言编程忘记free一样), 重复归还(可能需要做个循环判断一下是否池中存在此对象, 这也是个开销), 归还后仍旧使用对象(可能造成多个线程并发使用一个对象的情况)等问题。

参考:

对象池的介绍与使用_Dream_bin的博客-CSDN博客_对象池

brpc中资源池/对象池的源码剖析_华秋实的博客-CSDN博客_brpc resource_pool

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值