Smart pointers in C++ automatically delete the object they point to when the smart pointer goes out of scope. There are different types of smart pointers including std::auto_ptr, deep copy pointers, and reference counted pointers like boost::shared_ptr. Reference counted pointers use a reference counter to track the number of smart pointers pointing to an object. When that count reaches 0, the object is deleted. Smart pointers provide memory management benefits over raw pointers by automatically freeing memory and avoiding issues like dangling pointers.
2. 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.
3. 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
9. 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;
};
12. 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
13. 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
14. 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
15. 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
16. 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
17. 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;