POCO::Foundation 内存管理(二) SharedPtr

Poco::SharedPtr 实现了针对类的引用计数功能,而这些类不需要自己实现引用计数(AutoPtr的duplicate()和release()函数)。

Poco::SharedPtr有着和Poco::AutoPtr相同的解引用以及相关操作。

警告:赋值指向普通对象的指针到不同的Poco::SharedPtr将导致多个拥有者的产生,进而引起未定义的行为,换句话说,就是crash。

一旦你对一个对象使用Poco::SharedPtr,就不要再使用是想那个对象的指针了。

#include "Poco/SharedPtr.h"
#include <string>
#include <iostream>
using Poco::SharedPtr;
int main(int argc, char** argv)
{
std::string* pString = new std::string("hello, world!");
Poco::SharedPtr<std::string> p1(pString); // rc == 1
Poco::SharedPtr<std::string> p2(p1); // rc == 2
p2 = 0; // rc == 1,放弃共享拥有权
// p2 = pString; // BAD BAD BAD: multiple owners -> multiple delete
p2 = p1; // rc == 2
std::string::size_type len = p1->length(); // dereferencing with ->
std::cout << *p1 << std::endl; // dereferencing with *
return 0;
}
// rc == 0 -> deleted
先来看一个容易理解的例子:

有一份对象资源,分别被两个无任何关系的Poco::SharedPtr持有,所以各自的引用计数都是一。而在Poco::SharedPtr内部的析构函数中,会进行这个引用计数值的判断(先减1,再判断是否为0,为0就 delete 持有的资源)。好了,分别析构后,都得到引用计数为0,就产生了两次delete 资源,进而crash。

解决方法就是让其中一个Poco::SharedPtr的引用计数以另一个Poco::SharedPtr引用计数为基础,在其上加1.这样,最终得到0的情况只会发生在一个Poco::SharedPtr身上。

如何建立者两个Poco::SharedPtr的关系呢,那就是拷贝构造函数和=操作符。

SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr)
	{
		_pCounter->duplicate();//引用计数加1
	}
可以看到指向资源的_ptr都指向同一份资源,且_pCounter的值来源于另一个_pCounter。

SharedPtr& operator = (const SharedPtr& ptr)
	{
		return assign(ptr);
	}
SharedPtr& assign(const SharedPtr& ptr)
	{
		if (&ptr != this)
		{
			SharedPtr tmp(ptr);//执行拷贝构造函数,创建临时对象
			swap(tmp);
		}
		return *this;
	}
可以看到=操作符的内部产生了一个临时的tmp,通过swap把tmp的_ptr,_pCounter的值交换到this中相应的值中去。

除了管理单个对象,Poco::SharedPtr还可以管理对象数组。

char* arr = new char[100];
SharedPtr<char,Poco::ReferenceCounter,Poco::ReleaseArrayPolicy<char>> ptr(arr);
其实Poco::SharedPtr模板定义是:

template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >
class SharedPtr
因为第二个和第三个模板参数已经有默认的了,且都有确实实现,所以默认是管理一个对象。当把第三个参数换成内部已经存在的
Poco::ReleaseArrayPolicy<C>
后,从名字也可以看出,它可以管理数组了。

总结一下三个模板参数的意义:

class C:要管理的对象类型

class RC:执行引用计数的实现方法

class RP:实现最后析构被管理的对象的方法


谢谢观赏!




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值