POCO库Foundation之SharedPtr学习

来源:互联网 发布:快速备案域名 编辑:程序博客网 时间:2024/06/05 19:50

 POCO库说白了就是大牛写的一套C++工具集支持跨平台,里面包含了NET,XML,Thread各种模块,开设这个专栏就是记录我一点一滴的去学习POCO里面的代码设计


 在/FounDation/Core/SharedPtr.cpp看到了POCO库自己写了一个共享指针的实例,看了一下,不得不佩服里面的泛型封装设计

先粘贴远源码:

//// SharedPtr.h//// $Id: //poco/1.4/Foundation/include/Poco/SharedPtr.h#1 $//// Library: Foundation// Package: Core// Module:  SharedPtr//// Definition of the SharedPtr template class.//// Copyright (c) 2005-2008, Applied Informatics Software Engineering GmbH.// and Contributors.//// SPDX-License-Identifier:BSL-1.0//#ifndef Foundation_SharedPtr_INCLUDED#define Foundation_SharedPtr_INCLUDED#include "Poco/Foundation.h"#include "Poco/Exception.h"#include "Poco/AtomicCounter.h"#include <algorithm>namespace Poco {class ReferenceCounter/// Simple ReferenceCounter object, does not delete itself when count reaches 0.{public:ReferenceCounter(): _cnt(1){}void duplicate(){++_cnt;}int release(){return --_cnt;}int referenceCount() const{return _cnt.value();}private:AtomicCounter _cnt;};template <class C>class ReleasePolicy/// The default release policy for SharedPtr, which/// simply uses the delete operator to delete an object.{public:static void release(C* pObj)/// Delete the object./// Note that pObj can be 0.{delete pObj;}};template <class C>class ReleaseArrayPolicy/// The release policy for SharedPtr holding arrays.{public:static void release(C* pObj)/// Delete the object./// Note that pObj can be 0.{delete [] pObj;}};template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >class SharedPtr/// SharedPtr is a "smart" pointer for classes implementing/// reference counting based garbage collection./// SharedPtr is thus similar to AutoPtr. Unlike the/// AutoPtr template, which can only be used with/// classes that support reference counting, SharedPtr/// can be used with any class. For this to work, a/// SharedPtr manages a reference count for the object/// it manages./// /// SharedPtr works in the following way:/// If an SharedPtr is assigned an ordinary pointer to/// an object (via the constructor or the assignment operator),/// it takes ownership of the object and the object's reference /// count is initialized to one./// If the SharedPtr is assigned another SharedPtr, the/// object's reference count is incremented by one./// The destructor of SharedPtr decrements the object's/// reference count by one and deletes the object if the/// reference count reaches zero./// SharedPtr supports dereferencing with both the ->/// and the * operator. An attempt to dereference a null/// SharedPtr results in a NullPointerException being thrown./// SharedPtr also implements all relational operators and/// a cast operator in case dynamic casting of the encapsulated data types/// is required.{public:SharedPtr(): _pCounter(new RC), _ptr(0){}SharedPtr(C* ptr)try:_pCounter(new RC), _ptr(ptr){}catch (...) {RP::release(ptr);}template <class Other, class OtherRP> SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get())){_pCounter->duplicate();}SharedPtr(const SharedPtr& ptr): _pCounter(ptr._pCounter), _ptr(ptr._ptr){_pCounter->duplicate();}~SharedPtr(){try{release();}catch (...){poco_unexpected();}}SharedPtr& assign(C* ptr){if (get() != ptr){SharedPtr tmp(ptr);swap(tmp);}return *this;}SharedPtr& assign(const SharedPtr& ptr){if (&ptr != this){SharedPtr tmp(ptr);swap(tmp);}return *this;}template <class Other, class OtherRP>SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr){if (ptr.get() != _ptr){SharedPtr tmp(ptr);swap(tmp);}return *this;}SharedPtr& operator = (C* ptr){return assign(ptr);}SharedPtr& operator = (const SharedPtr& ptr){return assign(ptr);}template <class Other, class OtherRP>SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr){return assign<Other>(ptr);}void swap(SharedPtr& ptr){std::swap(_ptr, ptr._ptr);std::swap(_pCounter, ptr._pCounter);}template <class Other> SharedPtr<Other, RC, RP> cast() const/// Casts the SharedPtr via a dynamic cast to the given type./// Returns an SharedPtr containing NULL if the cast fails./// Example: (assume class Sub: public Super)///    SharedPtr<Super> super(new Sub());///    SharedPtr<Sub> sub = super.cast<Sub>();///    poco_assert (sub.get());{Other* pOther = dynamic_cast<Other*>(_ptr);if (pOther)return SharedPtr<Other, RC, RP>(_pCounter, pOther);return SharedPtr<Other, RC, RP>();}template <class Other> SharedPtr<Other, RC, RP> unsafeCast() const/// Casts the SharedPtr via a static cast to the given type./// Example: (assume class Sub: public Super)///    SharedPtr<Super> super(new Sub());///    SharedPtr<Sub> sub = super.unsafeCast<Sub>();///    poco_assert (sub.get());{Other* pOther = static_cast<Other*>(_ptr);return SharedPtr<Other, RC, RP>(_pCounter, pOther);}C* operator -> (){return deref();}const C* operator -> () const{return deref();}C& operator * (){return *deref();}const C& operator * () const{return *deref();}C* get(){return _ptr;}const C* get() const{return _ptr;}operator C* (){return _ptr;}operator const C* () const{return _ptr;}bool operator ! () const{return _ptr == 0;}bool isNull() const{return _ptr == 0;}bool operator == (const SharedPtr& ptr) const{return get() == ptr.get();}bool operator == (const C* ptr) const{return get() == ptr;}bool operator == (C* ptr) const{return get() == ptr;}bool operator != (const SharedPtr& ptr) const{return get() != ptr.get();}bool operator != (const C* ptr) const{return get() != ptr;}bool operator != (C* ptr) const{return get() != ptr;}bool operator < (const SharedPtr& ptr) const{return get() < ptr.get();}bool operator < (const C* ptr) const{return get() < ptr;}bool operator < (C* ptr) const{return get() < ptr;}bool operator <= (const SharedPtr& ptr) const{return get() <= ptr.get();}bool operator <= (const C* ptr) const{return get() <= ptr;}bool operator <= (C* ptr) const{return get() <= ptr;}bool operator > (const SharedPtr& ptr) const{return get() > ptr.get();}bool operator > (const C* ptr) const{return get() > ptr;}bool operator > (C* ptr) const{return get() > ptr;}bool operator >= (const SharedPtr& ptr) const{return get() >= ptr.get();}bool operator >= (const C* ptr) const{return get() >= ptr;}bool operator >= (C* ptr) const{return get() >= ptr;}int referenceCount() const{return _pCounter->referenceCount();}private:C* deref() const{if (!_ptr)throw NullPointerException();return _ptr;}void release(){poco_assert_dbg (_pCounter);int i = _pCounter->release();if (i == 0){RP::release(_ptr);_ptr = 0;delete _pCounter;_pCounter = 0;}}SharedPtr(RC* pCounter, C* ptr): _pCounter(pCounter), _ptr(ptr)/// for cast operation{poco_assert_dbg (_pCounter);_pCounter->duplicate();}private:RC* _pCounter;C*  _ptr;template <class OtherC, class OtherRC, class OtherRP> friend class SharedPtr;};template <class C, class RC, class RP>inline void swap(SharedPtr<C, RC, RP>& p1, SharedPtr<C, RC, RP>& p2){p1.swap(p2);}} // namespace Poco#endif // Foundation_SharedPtr_INCLUDED

下面是我仿造写的SharedPtr

#include <iostream>using namespace std;namespace shao {    //sharedPtr内部的引用计数class ReferenceCounter {public://构造的时候引用计数+1所以默认是为1ReferenceCounter():_counter(1){}        //引用计数+1void duplicate(){++_counter;}//引用计数-1int release(){return --_counter;}//获得当前对象的引用数int getReferenceCount() const{return _counter;}private:int _counter;};//释放指针的模板类 用来释放智能指针的对象template<class C>class ReleasePolicy{public:static void release(C* obj){   if (obj != NULL){delete obj;}}};template<class T,class RC = ReferenceCounter,class RP = ReleasePolicy<T>>class SharedPtr{public:SharedPtr():_ptr(0),_refCounter(new RC()){}SharedPtr(T* ptr):_ptr(ptr),_refCounter(new RC){}//拷贝构造 智能指针通过拷贝构造引用同一份内存,别忘记引用数+1操作SharedPtr(const SharedPtr& otherSharedPtr) :_ptr(otherSharedPtr._ptr), _refCounter(otherSharedPtr._refCounter){_refCounter->duplicate();}//重新指向,注意tmp是个临时变量,只是交换了内部指针,对引用数不会产生影响SharedPtr& assign(const SharedPtr& otherSharedPtr){if (&otherSharedPtr != this){SharedPtr tmp(otherSharedPtr);swap(tmp);}return *this;}void swap(SharedPtr& otherSharedPtr){std::swap(this->_ptr, otherSharedPtr._ptr);std::swap(this->_refCounter, otherSharedPtr._refCounter);}T* get() const{return _ptr;}//==重载判断是不是指向同一片内存bool operator ==(const SharedPtr& otherSharedPtr) const{return get() == otherSharedPtr.get();}bool operator ==(const T* ptr) const{return get() == ptr;}bool operator != (const SharedPtr& ptr) const{return get() != ptr.get();}T* operator ->(){return _ptr;}T& operator*(){return *_ptr;}int getRefCount(){if (_refCounter == NULL) {return 0;}return _refCounter->getReferenceCount();}        ~SharedPtr(){relese();}//如果引用数减1 后为0  说明没有指针指向该内存就应该释放内存实现智能指针的核心原理void relese(){int count = _refCounter->release();if (count == 0){RP::release(_ptr);_ptr = 0;delete _refCounter;_refCounter = 0;}}private:    T* _ptr;RC* _refCounter;};class Student{private:int _age;public:Student(int age) : _age(age){}void printAge(){std::cout << "My Age is = " << _age << endl;}};}void main() {shao::SharedPtr<shao::Student> _SharedPtr1(new shao::Student(12));    shao::SharedPtr<shao::Student> _SharedPtr2(new shao::Student(22));shao::SharedPtr<shao::Student> _SharedPtr3(_SharedPtr1);_SharedPtr1->printAge();_SharedPtr2->printAge();cout << "==============" << endl;_SharedPtr1.assign(_SharedPtr2);cout << _SharedPtr2.getRefCount() << endl;cout << "Nanjing By Zhongqi.Shao" << endl;system("pause");}



通过这个代码更容易理解智能指针的原理




原创粉丝点击