POCO C++库学习和分析 -- 内存管理 (二)
3. SharedPtr
SharedPtr是Poco库中基于引用计数实现的另外一种智能指针。同AutoPtr相比,Poco::SharedPtr主要用于为没有实现引用计数功能的类(换句话说,也就是该类本身不是引用计数对象)提供引用计数服务,实现动态地址的自动回收。
可以这么说,Poco::AutoPtr是使用继承关系来实现的智能指针,而Poco::SharedPtr是聚合方法实现的智能指针。
3.1 SharedPtr的类图
首先来看一下SharedPtr的类图:
从类图中可以看到SharedPtr是对引用计数和原生指针封装。其中有成员指针_ptr,指向任意类型的C;同时还存在一个引用计数对象的指针_pCounter,指向任意一个实现了引用计数的类。当然在Poco库中提供了ReferenceCount的默认实现,类ReferenceCounter。
比较类ReferenceCounter和AutoPtr中依赖的类RefCountedObject,可以发现其实现相同,本质上就是一个东西。Poco库中之所以把两者分开,我想是为了明确的表示类与类之间的关系。ReferenceCounter用于组合,而RefCountedObject用于继承。
SharedPtr在实现模板的时候,还预留了RP参数,这是一个释放策略,用于调整SharedPtr在释放数组和单个对象之间不同策略的转换。
[cpp] view plaincopy
1. template
4. // ... 5. }
其中C为对象原生指针,RC为SharedPtr管理的引用计数对象,RP为内存释放策略。
3.2 SharedPtr操作符和值语义
1. Poco::SharedPtr同样支持关系操作符==, !=, <, <=, >, >=;
2. 当Poco::SharedPtr中原生指针为空时,使用解引用操作符“*”或者\,Poco::SharedPtr会抛出一个NullPointerException 异常。
3. Poco::SharedPtr同样支持全值语义,包括默认构造函数,拷贝构造函数,赋值函数并且同样可以用于各类容器(如std::vector 和 std::map)
[cpp] view plaincopy
1. SharedPtr& operator = (C* ptr) 2. {
3. return assign(ptr); 4. } 5.
6. SharedPtr& assign(C* ptr) 7. {
8. if (get() != ptr) 9. {
10. RC* pTmp = new RC; 11. release(); 12. _pCounter = pTmp; 13. _ptr = ptr; 14. }
15. return *this; 16. } 17.
18. void release()
19. {
20. poco_assert_dbg (_pCounter); 21. int i = _pCounter->release(); 22. if (i == 0) 23. {
24. RP::release(_ptr); 25. _ptr = 0; 26.
27. delete _pCounter; 28. _pCounter = 0; 29. } 30. }
注意,在SharedPtr赋值操作符\中的操作,对于原生指针_ptr的操作策略是交换,而引用计数对象_pCounter的策略是先new一个,再交换。
4. 可以用SharedPtr::isNull()和SharedPtr::operator ! () 去检查内部的原生指针是否为空。
3.3 SharedPtr和Cast类型转换
同普通指针类似,Poco::SharedPtr支持cast操作符。这在 template
[cpp] view plaincopy
1. template
2. SharedPtr
3. /// Casts the SharedPtr via a dynamic cast to the given type. 4. /// Returns an SharedPtr containing NULL if the cast fails. 5. /// Example: (assume class Sub: public Super) 6. /// SharedPtr
10. Other* pOther = dynamic_cast
12. return SharedPtr
Poco::SharedPtr中类型转换总是安全的,在其内部实现时,使用了dynamic_cast ,所以一个不合法的转换,会导致原生指针为空。
Poco::SharedPtr中赋值操作符的兼容性通过构造函数和赋值操作符共同完成。
[cpp] view plaincopy
1. template
2. SharedPtr& operator = (const SharedPtr
4. return assign
6.
7. template
8. SharedPtr& assign(const SharedPtr
10. if (ptr.get() != _ptr) 11. {
12. SharedPtr tmp(ptr); 13. swap(tmp); 14. }
15. return *this; 16. } 17.
18. template
19. SharedPtr(const SharedPtr er*>(ptr.get())) 20. { 21. _pCounter->duplicate(); 22. } 下面是关于操作符的一个例子: [cpp] view plaincopy 1. #include \ 2. class A 3. { 4. public: 5. virtual ~A() 6. {} 7. }; 8. class B: public A 9. { 10. }; 11. class C: public A 12. { 13. }; 14. int main(int argc, char** argv) 15. { 16. Poco::SharedPtr pA; 17. Poco::SharedPtr pB(new B); 18. pA = pB; // okay, pB is a subclass of pA 19. pA = new B; 20. // pB = pA; // will not compile 21. pB = pA.cast(); // okay 22. Poco::SharedPtr 23. pB = pC.cast(); // pB is null 24. return 0; 25. }
相关推荐: