Smart Pointers in C++


This article is mainly from the Microsoft C++ Documentation. In modern C++ programming, the Standard Library includes smart pointers, which are used to help ensure that programs are free of memory and resource leaks and are exception-safe.


Raw Pointers and Smart Pointers

Smart pointers are defined in the std namespace in the memory header file. They are crucial to the RAII (Resource Acquisition Is Initialization) programming idiom. The main principle of RAII is to give ownership of any heap-allocated resource to a stack-allocated object whose destructor contains the code to delete or free the resource and also any associated cleanup code.

In modern C++, raw pointers are only used in small code blocks where performance is critical and there is no chance of confusion about ownership. In most cases, when you initialize a raw pointer or resource handle to point to an actual resource, pass the pointer to a smart pointer immediately.

The following example compares a raw pointer declaration to a smart pointer declaration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void UseRawPointer() {
    // Using a raw pointer
    Song* pSong = new Song(L"Nothing on You", L"Bruno Mars");

    // Use pSong ...

    // Don't forget to delete!
    delete pSong;
}

void UseSmartPointer() {
    // Declare a smart pointer on stack and pass it the raw pointer.
    unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));

    // Use song2 ...
    wstring s = song2->duration_;
    // ...
} // song2 is deleted automatically here.

A smart pointer is a class template declared on the stack, and initialized by using a raw pointer that points to a heap-allocated object. After the smart pointer is intialized, it owns the raw pointer. This means that the smart pointer is responsible for deleting the memory that the raw pointer specifies. The smart pointer destructor contains the call to delete, and because the smart pointer is declared on the stack, its destructor is invoked when the smart pointer goes out of scope.

Access the encapsulated pointer by using the familiar pointer operators, -> and *, which the smart pointer class overloads to return the encapsulated raw pointer.

The following example shows how a unique_ptr smart pointer type could be used to encapsulate a pointer to a large object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class LargeObject {
public:
    void DoSomething() {}
};

void ProcessLargeObject(const LargeObject& lo) {}

void SmartPointerDemo() {
    // Create the object and pass it to a smart pointer
    unique_ptr<LargeObject> pLarge(new LargeObject());

    // Call a method on the object
    pLarge->DoSomething();

    // Pass a reference to a method
    ProcessLargeObject(*pLarge);

} //pLarge is deleted automatically when function block goes out of scope. 

The example demonstrates the following essential steps for using smart pointers.

  1. Declare the smart pointer as an automatic (local) variable.
  2. In the type parameter, specify the pointed-to type of the encapsulated pointer.
  3. Pass a raw pointer to a new-ed object in the smart pointer constructor.
  4. Use the overloaded -> and * operators to access the object.
  5. Let the smart pointer delete the object.


Kinds of Smart Pointers

The unique_ptr allows exactly one owner of the underlying pointer. Can be moved to a new owner, but not copied or shared.

The shared_ptr is the reference-counted smart pointer. Use when you want to assign one raw pointer to multiple owners. The raw pointer is not deleted until all share_ptr owners have gone out of scope or have otherwise given up ownership.

The weak_ptr is a special-case smart pointer for use in conjunction with shared_ptr. A weak_ptr provides access to an object that is owned by one or more shared_ptr instances, but does not participate in reference counting. Use when you want to observe an object, but do not require it to remain alive. Required in some cases to break circular references between shared_ptr instances.




Related Posts

Weak_Ptr in C++

Sometimes an object must store a way to access the...

Unique_Ptr in C++

A unique_ptr does not share its pointer. It cannot be...

Smart Pointers in C++

In modern C++ programming, the Standard Library includes smart pointers,...

Shared_Ptr in C++

The shared_ptr type is a smart pointer that is designed...