Smart Pointer in C++

ssuserc3cb5d 297 views 21 slides Nov 30, 2016
Slide 1
Slide 1 of 21
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21

About This Presentation

No description available for this slideshow.


Slide Content

Smart Pointer in C++
韩永泉
2013.9.23

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.

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

auto_ptr<T>

Deep Copy Ptr

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

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

Some free functions(智能指针接口的一部分 )
template<class T> inline
bool operator< (const SmartPtr<T>& left, const SmartPtr<T>& right);
template<class T> inline
bool operator==(const SmartPtr<T>& left, const SmartPtr<T>& right);
template<class T> inline
bool operator!=(const SmartPtr<T>& left, const SmartPtr<T>& right);
template<class T> inline
bool operator> (const SmartPtr<T>& left, const SmartPtr<T>& right);
template<class T> inline
bool operator<=(const SmartPtr<T>& left, const SmartPtr<T>& right);
template<class T> inline
bool operator>=(const SmartPtr<T>& left, const SmartPtr<T>& right);
* How to implement them?
template<class T> inline
void swap(SmartPtr<T>& left, SmartPtr<T>& 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<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); }
……
};
/* ??? */

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 NULL
cmdPtr3 = 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

Some usages of smart pointer
Singleton 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

Some usages of SmartPtr
Data 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

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

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

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;

Thread Safety(copy simultaneously)

Thread Safety(destroy simultaneously)

Thread Safety(destroy before copy)

Q&A
Tags