smart pointer in c++

Download Smart Pointer in C++

Post on 20-Jan-2017

33 views

Category:

Documents

0 download

Embed Size (px)

TRANSCRIPT

  • Smart Pointer in C++

    2013.9.23

  • Whats the main/most important characteristic?

    Delete the object it points to and release the resource/memory automatically when the smart pointer object goes out of its range.

  • Some kinds of Smart Pointer

    std::auto_ptr Deep copy ptr Ref counted ptr(intrusive / nonintrusive), such as

    boost::shared_ptr, STL/tr1/boost_shared_ptr, self-defined

  • auto_ptr

    newRealObject T

    std::auto_ptr p1

    copy

    std::auto_ptr p2 = p1;

    newRealObject T

    std::auto_ptr p1

    std::auto_ptr p2

    X

  • Deep Copy Ptr

    newRealObject T

    DeepCopy_ptr p1

    copy

    DeepCopy_ptr p2=p1

    newRealObject T

    DeepCopy_ptr p1

    DeepCopy_ptr p2

    newRealObject T

    Deep copy

  • How to implement a RefCounted SmartPtr class?Non-intrusive Reference Counter(solution 1)Non-intrusive Reference Counter(solution 2)

    Diameter

  • How to implement a RefCounted SmartPtr class?Intrusive Reference Counter(solution 1)class RefCountedBase{public: virtual ~RefCountedBase() {} void addRef() { ++m_refCount; } void release() { if (--m_refCount == 0) delete this; }protected: volatile unsigned int m_refCount;};class RealObject : public RefCountedBase{public: private: };

  • What does NULL smart pointer like?

  • What does the smart pointer interface like?

    template class SmartPtr {public: SmartPtr(); explicit SmartPtr(T *pObj); SmartPtr(const SmartPtr& other); SmartPtr& operator=(const SmartPtr& other); SmartPtr& operator=(T *pObj); ~SmartPtr(); bool operator ! () const; // such as if (!sp) operator void* () const; // such as if (sp == NULL/0) // operator bool () const; // not allowed! T* operator -> (); const T* operator -> () const; T& operator * (); const T& operator * () const;

    #ifdef _DEBUG T* get() const; // DO NOT delete the returned raw pointer! bool unique() const; // does the current refcount equal to 1? uint refCount() const;#endif // _DEBUG

    void detach(); // detach current smart pointer from real object, and decrease refcount by 1 void swap(SmartPtr& other); // swap two smart pointers which point to two different objects respectively

    private: T * m_pRealObject; uint * m_pRefCounter;};

  • Some free functions()

    template inlinebool operator< (const SmartPtr& left, const SmartPtr& right);

    template inlinebool operator==(const SmartPtr& left, const SmartPtr& right);

    template inlinebool operator!=(const SmartPtr& left, const SmartPtr& right);

    template inlinebool operator> (const SmartPtr& left, const SmartPtr& right);

    template inlinebool operator=(const SmartPtr& left, const SmartPtr& right);

    * How to implement them?

    template inlinevoid swap(SmartPtr& left, SmartPtr& right){ left.swap(right); }

  • Implement some member functions

    public: SmartPtr() : m_pRealObject(NULL), m_pRefCounter(NULL) { } explicit SmartPtr(T *pObj) { if (pObj != NULL) { m_pRefCounter = new uint(1); m_pRealObject = pObj; }else { m_pRefCounter = NULL; m_pRealObject = NULL; } } SmartPtr(const SmartPtr& other) { if ( (m_pRealObject = other.m_pRealObject) != NULL) { m_pRefCounter = other.m_pRefCounter; ++(*m_pRefCounter); /* thread safe ? */ } else { m_pRefCounter = NULL; } } ~SmartPtr() { if (m_pRealObject != NULL) { if (- -(*m_pRefCounter) == 0) /* thread safe ? */ { delete m_pRefCounter; delete m_pRealObject; } } } bool operator ! () const { (m_pRealObject == NULL) ? true : false; } T* operator -> () { assert(m_pRealObject != NULL); return m_pRealObject; } T& operator * () { assert(m_pRealObject != NULL); return (*m_pRealObject); } };/* ??? */

  • How to use a RefCounted Smart Pointer class?Smart pointer is a class template to encapsulate a raw pointer (T*) which points to a real object/variable.

    Provides the same behavior with raw pointers in object/class manner.

    Share the same one real object simultaneously among several smart pointers with the same type.

    Give it a meaningful type name, but not declare variables directly.

    A smart pointer of base class type can points to an object of derived class type.

    template class SmartPtr {public: private: T* m_rep; };

    typedef SmartPtr CommandSmartPtr;CommandSmartPtr cmdPtr(new Command);cmdPtr->Do(); cmdPtr->ReDo(); cmdPtr->UnDo();(*cmdPtr).Do; (*cmdPtr).ReDo();

    CommandSmartPtr cmdPtr2(cmdPtr);CommandSmartPtr cmdPtr3; // initialize to NULLcmdPtr3 = cmdPtr2;

    typedef SmartPtr CommandSmartPtr; ()CommandSmartPtr cmdPtrx; ()SmartPtr cmdPtrx; (x)

    class Derived : public Base{};typedef SmartPtr BaseSmartPtr;BaseSmartPtr ptrBase(new Derived);ptrBase->VirtualFunction();12345

    Diameter

  • Some usages of smart pointerSingleton pattern class SomeClass { public: ~SomeClass(); static SomeClass* get_instance() { static SomeClass *pOnly = new SomeClass; return (pOnly); } private: SomeClass(); SomeClass(const SomeClass&); void operator=(const SomeClass&); }; typedef SmartPtr SomeClassSmartPtr; SomeClassSmartPtr GetSomeClassSingleton() { return SomeClass::get_instance(); }

    Function parameter and return value void SetSomeClass(SomeClassSmartPtr pSomeClassObject); SomeClassSmartPtr getSomeClass() const;

    Global objects SomeClassSmartPtr g_pSomeClassVariable1(new SomeClass); static SomeClassSmartPtr gs_pSomeClassVariable2(new SomeClass);123

  • Some usages of SmartPtrData Member SomeClassSmartPtr m_pSomClassObject; OtherClassSmartPtr m_pOtherClassObject;

    STL container element typedef std::list SomeClassList; SomeClassList someObjList; someObjList.push_back(new SomeClass); someObjList.push_back(new SomeClass); someObjList.push_back(new SomeClass); someObjList.sort();

    All other non-copyable classes Always use its smart pointer form anywhere, but not its reference/raw pointer/object.

    In other design patterns, such as Factory, Command, Observer, etc.

    Could you please give some other usages?56784

  • Whats the benefits we can get from it?Release the resource(memory/device/port,etc.) automatically when there are none any reference to it; so neednt remember to release it manually by any other programmer, especially among different modules

    Avoid the overheads of object copy

    Dont lose the polymorphic behavior of real object

    Can be used safely in any STL container

    ?12345

  • Some Notes

    Smart pointer that points to one single object cant support operator ++, --, [], +n, -n, etc., but they are supported by raw pointer; Dont declare the corresponding smart pointer type for an incomplete class like this

    class Command; // incomplete class declaration! typedef SmartPtr CommandSmartPtr; // Instanciate SmartPtr template for Command? Because the behavior of the result type CommandSmartPtr is possible dependent on the C++ compiler implementation we are using. So, the perfect practice is to declare it exactly after the class definition, such as class Command { public: virtual void Do(); }; typedef SmartPtr CommandSmartPtr; typedef std::set CommandList; ; // all other Command-related types declarationIf the real object is not created by operator new, how to deal with it?

    (1) Specialize the destructor of smart pointer for the real object class; (2) add a new template parameter as the deleter of the real object, refer to boost::shared_ptr;Thread-Safety topic?

    Thread-safety of our software/program should not only depend on the smart pointer, because this is not its responsibility.1234

  • cyclic pointer#include

    class Foo{public: ~Foo() {} void AddBar(BarSmartPtr p); private: BarList m_barList;};

    typedef SmartPtr FooSmartPtr;#include // Is correct? No!class Foo;

    class Bar{public: ~Bar() { delete m_pOwner; } // Is correct? No! void SetOwner(FooSmartPtr p); ; // Is correct? No! void SetOwner(Foo *p); // OK! private: FooSmartPtr m_pOwner; // Is correct? No! Foo *m_pOwner; // loop back, OK!};

    typedef SmartPtr BarSmartPtr;typedef std::list BarList;

    Foo x;

    ...

    Bar

    Bar

    m_pOwner

  • Thread Safety(copy simultaneously)

    newRealObject T

    global sp1

    1

    T1

    newRealObject T

    sp1

    sp2

    2

    Copy

    Destroy sp2

    3

    T2

    sp3

    Copy

    Destroy sp3

  • Thread Safety(destroy simultaneously)

    T1

    newRealObject T

    sp1

    1

Recommended

View more >