smart pointer in c++

21
Smart Pointer in C++ 韩韩韩 2013.9.23

Upload: -

Post on 20-Jan-2017

62 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Smart Pointer in C++

Smart Pointer in C++韩永泉2013.9.23

Page 2: Smart Pointer in C++

What’s 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.

Page 3: Smart Pointer in C++

Some kinds of Smart Pointer

std::auto_ptr<T>

Deep copy ptr

Ref counted ptr(intrusive / nonintrusive), such as

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

Page 4: Smart Pointer in C++

auto_ptr<T>

newRealObject T

std::auto_ptr<T> p1

copy

std::auto_ptr<T> p2 = p1;

newRealObject T

std::auto_ptr<T> p1

std::auto_ptr<T> p2

X

Page 5: Smart Pointer in C++

Deep Copy Ptr

newRealObject T

DeepCopy_ptr<T> p1

copy

DeepCopy_ptr<T> p2=p1

newRealObject T

DeepCopy_ptr<T> p2 newRealObject T

Deep

copyDeepCopy_ptr<T> p1

Page 6: Smart Pointer in C++

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

Non-intrusive Reference Counter(solution 2)

Page 7: Smart Pointer in C++

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: ……};

Page 8: Smart Pointer in C++

What does NULL smart pointer like?

Page 9: Smart Pointer in C++

What does the smart pointer interface like?template<class T> class SmartPtr {public: SmartPtr(); explicit SmartPtr(T *pObj); SmartPtr(const SmartPtr<T>& other); SmartPtr<T>& operator=(const SmartPtr<T>& other); SmartPtr<T>& 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<T>& other); // swap two smart pointers which point to two different objects respectively

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

Page 10: Smart Pointer in C++

Some free functions(智能指针接口的一部分 )template<class T> inlinebool operator< (const SmartPtr<T>& left, const SmartPtr<T>& right);

template<class T> inlinebool operator==(const SmartPtr<T>& left, const SmartPtr<T>& right);

template<class T> inlinebool operator!=(const SmartPtr<T>& left, const SmartPtr<T>& right);

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

template<class T> inlinebool operator<=(const SmartPtr<T>& left, const SmartPtr<T>& right);

template<class T> inlinebool operator>=(const SmartPtr<T>& left, const SmartPtr<T>& right);

* How to implement them?template<class T> inlinevoid swap(SmartPtr<T>& left, SmartPtr<T>& right){ left.swap(right); }

Page 11: Smart Pointer in C++

Implement some member functionspublic: 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<T>& 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); } ……};

/* ??? */

Page 12: Smart Pointer in C++

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 T> class SmartPtr {public: ……private: T* m_rep; ……};

typedef SmartPtr<Command> 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<Command> CommandSmartPtr; (√)CommandSmartPtr cmdPtrx; (√)SmartPtr<Command> cmdPtrx; (x)

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

1

2

3

4

5

Page 13: Smart Pointer in C++

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<SomeClass> 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);

1

2

3

Page 14: Smart Pointer in C++

Some usages of SmartPtrData Member SomeClassSmartPtr m_pSomClassObject; OtherClassSmartPtr m_pOtherClassObject;

STL container element typedef std::list<SomeClassSmartPtr> 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 it’s smart pointer form anywhere, but not it’s reference/raw pointer/object.

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

Could you please give some other usages?

5

6

7

8

4

Page 15: Smart Pointer in C++

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

Avoid the overheads of object copy

Don’t lose the polymorphic behavior of real object

Can be used safely in any STL container

?

1

2

3

4

5

Page 16: Smart Pointer in C++

Some Notes• Smart pointer that points to one single object can’t support operator ++, --, [], +n, -n, etc.,

but they are supported by raw pointer; • Don’t declare the corresponding smart pointer type for an incomplete class like this class Command; // incomplete class declaration! typedef SmartPtr<Command> 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<Command> CommandSmartPtr; typedef std::set<CommandSmartPtr> CommandList; ……; // all other Command-related types declaration

• If 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.

1

2

3

4

Page 17: Smart Pointer in C++

cyclic pointer#include <bar.h>

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

typedef SmartPtr<Foo> FooSmartPtr;

#include <foo.h> // 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<Bar> BarSmartPtr;typedef std::list<BarSmartPtr> BarList;

Foo x;

...

Bar Bar

m_pOwner m_pOwner

Bar

m_pOwner

Bar

m_pOwner

Bar

m_pOwner...

Page 18: Smart Pointer in C++

Thread Safety(copy simultaneously)

newRealObject T

global sp1

1

T1new

RealObject Tsp1

sp2

2

Cop

y

Destroy sp2

3

T2

sp3

Copy

Destroy sp3

Page 19: Smart Pointer in C++

Thread Safety(destroy simultaneously)

T1

newRealObject T

sp1

1

create

T2pthread_create(sp1)

sp2

Copy sp1

2

Destroy sp1 Destroy sp2

Page 20: Smart Pointer in C++

T2pthread_create(sp1)

Thread Safety(destroy before copy)

T1

newRealObject T

sp1

1

create

Destroy sp1

sp2

Copy sp1

2

Destroy sp2

Page 21: Smart Pointer in C++

Q&A