C++对象池自动回收技术

什么是对象池

    类似于内存池机制,对象池中存放有已经分配好的对象,当需要使用时,只需要向对象池申请。而不再使用时,则由对象池自动回收。适用于一下情况:

  • 对象可重用
  • 对象创建开销大
  • 对象创建频繁

如何实现自动回收

    C++11中的智能指针可以自定义删除器,在回收时智能指针自动调用自定义的删除器实现对象的自动回收。那么何时定义删除器呢?如果我们在添加对象时定义删除器,那么对象被回收后就失去了自定义的删除器。因此我们可以在获取对象时,定义删除器,如此分配出去的对象总是能够自动回收。另外使用的智能指针是unique_ptr,而不是shared_ptr,因为无法直接将shared_ptr的删除器修改为自定义删除器,虽然可以通过重新创建一个新对象,把原对象拷贝过来的做法来实现,但是这样做效率比较低。以下是实现过程:

class A {
public:
	int m;
public:
	A(int x = 0) : m(x) {  }
	~A() {}
};

template <class T>
class SimpleObjectPool
{
public:
	using DeleterType = std::function<void(T*)>;
	void add(std::unique_ptr<T> t)        //向对象池添加一个对象
	{
		pool_.push_back(std::move(t));
	}
	std::unique_ptr<T, DeleterType> get() //从对象池获取一个对象
	{
		try {
			if (pool_.empty())
			{
				throw std::logic_error("no more object");
			}
		}
		catch (logic_error& e) {
			cout << e.what() << endl;
			return nullptr;
		}
		//先释放一个对象,然后为其添加一个自定义的删除器。即ptr获得了对象池的一个对象,
		//并且拥有了一个自定义的删除器,其功能是将对象放回对象池,而不是销毁
		std::unique_ptr<T, DeleterType> ptr(pool_.back().release(), [this](T* t) {
			pool_.push_back(std::unique_ptr<T>(t));
		});
		pool_.pop_back();
		return std::move(ptr); //转化为右值,否则无法被赋值
	}
	bool empty() const
	{
		return pool_.empty();
	}
	size_t size() const
	{
		return pool_.size();
	}
private:
	std::vector<std::unique_ptr<T>> pool_;
};

void test_object_pool()
{
	SimpleObjectPool<A> p;
	p.add(std::unique_ptr<A>(new A()));
	p.add(std::unique_ptr<A>(new A()));
	{
		auto t = p.get();
		p.get();
	}
	{
		auto t1 = p.get();
		auto t2 = p.get();
		auto t3 = p.get();
	}
	std::cout << p.size() << std::endl;
}

int main() {
	test_object_pool();
	return 0;
}

输出如下:

no more object
2

总结

  • 因为申请的对象有自定义的删除器,因此申请的对象离开作用域后,就会被对象池自动回收
  • 对象池的对象的删除器是默认的删除器,只有被分配出去的对象才有自定义的删除器,因为这样可以保证对象池在离开作用域后,能够正确的自动释放所有对象的资源。
  • 不使用shared_ptr的原因主要是,shared_ptr不能像unique_ptr那样使用release来主动释放资源所有权。只能通过如下方式:
auto p = pool_.back();
shared_ptr<T> ptr(p, [this](T* t) { //语法不正确,因为同一个对象的shared_ptr指针的删除器必须相同,如果正确,
	pool_.push_back(shared_ptr<T> t); //那么ptr和p将使用不同的删除器,显然不合理
});
pool_pop_back();
return ptr;
shared_ptr<T> p = pool_.back();
std::shared_ptr<T> ptr(new T(*p.get()), [this](T* t) { //语法正确,但是需要重新创建并拷贝原对象,效率低
	pool_.push_back(std::shared_ptr<T>(t));
});
return ptr;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值