一、介绍
C++对象池是一种常用的内存管理技术,它可以提高程序的效率和性能。对象池是一种预先分配好一定数量的对象内存池,当需要使用对象时,从对象池中获取一个空闲的对象,使用完毕后再将其放回池中,以便下次使用。这样可以避免频繁的内存分配和释放,减少内存碎片,提高程序的效率和性能。
二、对象池解决什么问题
对象池通常用于需要频繁创建和销毁对象的场景,如网络编程中的连接池、线程池、对象缓存等。C++中可以使用标准库中的std::vector
和std::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一样), 重复归还(可能需要做个循环判断一下是否池中存在此对象, 这也是个开销), 归还后仍旧使用对象(可能造成多个线程并发使用一个对象的情况)等问题。
参考: