Poco C ++ library learning and analysis-memory management (2)
3. sharedptr
Sharedptr is another smart pointer implemented based on reference count in the POCO library. Compared with autoptr, Poco: sharedptr is mainly used to provide reference counting service for classes that do not implement the reference counting function (in other words, this class itself is not a reference counting object, automatically reclaim dynamic addresses.
In this case, Poco: autoptr is a smart pointer implemented by using an inheritance relationship, while poco: sharedptr is a smart pointer implemented by an aggregation method.
3.1 sharedptr class diagram
First, let's take a look at the sharedptr class diagram:
From the class diagram, we can see that sharedptr encapsulates the reference count and native pointer. There is a member pointer _ PTR pointing to any type of C. There is also a pointer _ pcounter that references the counting object, pointing to any class that implements reference counting. Of course, the default Implementation of referencecount is provided in the POCO library, and the class is referencecounter.
Comparing referencecounter and refcountedobject dependent classes in autoptr, we can find that the implementation is the same, which is essentially a thing. The reason why the POCO library separates the two is to explicitly indicate the relationship between classes. Referencecounter is used for combination, while refcountedobject is used for inheritance.
When implementing the template, sharedptr also reserves the RP parameter, which is a release policy used to adjust the conversion of sharedptr policies between the released array and a single object.
template <class C, class RC = ReferenceCounter, class RP = ReleasePolicy<C> >class SharedPtr{// ...}
C is the object native pointer, RC is the reference counting object managed by sharedptr, and RP is the memory release policy.
3.2 sharedptr operator and value Semantics
1. Poco: sharedptr also supports Relational operators = ,! =, <, <=,>,> =;
2. When the null nullpointerexception occurs in poco: sharedptr, an nullpointerexception exception is thrown by using the unreferenced operator "*" or "->", Poco: sharedptr.
3. Poco: sharedptr also supports full-value semantics, including default constructor, copy constructor, and assign value function, which can also be used in various containers (such as STD: vector and STD: map)
SharedPtr& operator = (C* ptr){return assign(ptr);}SharedPtr& assign(C* ptr){if (get() != ptr){RC* pTmp = new RC;release();_pCounter = pTmp;_ptr = ptr;}return *this;}void release(){poco_assert_dbg (_pCounter);int i = _pCounter->release();if (i == 0){RP::release(_ptr);_ptr = 0;delete _pCounter;_pCounter = 0;}}
Note: For operations in the sharedptr value assignment operator "=", the operation policy for native pointer _ PTR is exchange, while the policy for referencing counter object _ pcounter is first new and then exchange.
4. You can use sharedptr: isnull () and sharedptr: Operator! () To check whether the internal native pointer is null.
3.3 sharedptr and cast type conversion
Similar to common pointers, Poco: sharedptr supports the cast operator. This is implemented in template <class other> sharedptr <other> cast () Const. Its definition is as follows:
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>();}
Poco: The type conversion in sharedptr is always safe. dynamic_cast is used in its internal implementation. Therefore, an invalid conversion will lead to null native pointers.
Poco: Compatibility of value assignment operators in sharedptr is achieved through constructor and value assignment operator.
template <class Other, class OtherRP>SharedPtr& operator = (const SharedPtr<Other, RC, OtherRP>& ptr){return assign<Other>(ptr);}template <class Other, class OtherRP>SharedPtr& assign(const SharedPtr<Other, RC, OtherRP>& ptr){if (ptr.get() != _ptr){SharedPtr tmp(ptr);swap(tmp);}return *this;}template <class Other, class OtherRP> SharedPtr(const SharedPtr<Other, RC, OtherRP>& ptr): _pCounter(ptr._pCounter), _ptr(const_cast<Other*>(ptr.get())){_pCounter->duplicate();}
The following is an example of operators:
#include "Poco/SharedPtr.h"class A{public:virtual ~A(){}};class B: public A{};class C: public A{};int main(int argc, char** argv){Poco::SharedPtr<A> pA;Poco::SharedPtr<B> pB(new B);pA = pB; // okay, pB is a subclass of pApA = new B;// pB = pA; // will not compilepB = pA.cast<B>(); // okayPoco::SharedPtr<C> pC(new C);pB = pC.cast<B>(); // pB is nullreturn 0;}
3.4 precautions for using sharedptr
From the above we can see that poco: sharedptr has some features similar to poco: autoptr, such as unreferencing and value assignment operators. However, unlike poco: autoptr, when the value assignment operator "=" is used to assign a sharedptr to a native pointer, it is not allowed to assign this native pointer to another sharedptr. At this time, both sharedptr will claim the ownership of the object and cause the program crash. Although this is not recommended in autoptr, it provides a solution using the following functions and to "shared = true ".
AutoPtr::AutoPtr(C* pObject, bool shared); AutoPtr& AutoPtr::assign(C* pObject, bool shared);
For poco: sharedptr, the best way is to never try to use a native pointer to the object once the object ownership is obtained using sharedptr.
The following is an example of 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 == 1Poco::SharedPtr<std::string> p2(p1); // rc == 2p2 = 0; // rc == 1// p2 = pString; // BAD BAD BAD: multiple owners -> multiple deletep2 = p1; // rc == 2std::string::size_type len = p1->length(); // dereferencing with ->std::cout << *p1 << std::endl; // dereferencing with *return 0;}// rc == 0 -> deleted
3.5 sharedptr and array
The default sharedptr deletion policy is to delete objects. If you use an array when creating an object and delegate it to sharedptr, you must use the corresponding array deletion policy. In this case, the releasepolicy class releasearraypolicy should be used in the sharedptr template parameters.
The following is another example:
template <class C>class ArrayReleasePolicy{public:static void release(C* pObj)/// Delete the object./// Note that pObj can be 0.{delete [] pObj;}};char* pStr = new char[100];SharedPtr<char, Poco::ReferenceCounter, ArrayReleasePolicy> p(pStr);
3.6 others
Compared with the boost library, sharedptr in Poco is similar to shared_ptr In the boost library and similar in behavior, though different in implementation.
(Copyright, reprinted, please indicate the author and the source http://blog.csdn.net/arau_sh/article/details/8636559)