Skip to main content
C++ Fundamentals for Beginners to Advanced
CHAPTER 25 Beginner

Smart Pointers and Modern C++

Updated: May 17, 2026
5 min read

# CHAPTER 25

Smart Pointers and Modern C++

1. Introduction

For decades, the biggest criticism of C++ was Memory Leaks. If a programmer used new but forgot delete (or if an exception caused the program to skip the delete line), memory was lost forever. In 2011, Modern C++ (C++11) introduced Smart Pointers, practically eliminating the need for raw pointers and manual memory management.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Explain why raw pointers (*) are dangerous.
  • Use std::uniqueptr for exclusive ownership.
  • Use std::sharedptr for shared ownership.
  • Understand std::weakptr and cyclic references.
  • Safely allocate memory using std::makeunique.

3. The Problem with Raw Pointers

cpp
123456789
void doWork() {
    int* ptr = new int(10);
    
    if (someConditionFails()) {
        throw runtime_error("Error!"); // We jump out here...
    }
    
    delete ptr; // ...this is NEVER reached. Memory Leak!
}

4. std::uniqueptr (Exclusive Ownership)

A uniqueptr owns the memory exclusively. No two uniqueptrs can point to the same memory. When the uniqueptr goes out of scope, it automatically calls delete for you.

*(Requires #include <memory>)*

cpp
12345678910111213141516171819202122232425
#include <iostream>
#include <memory>
using namespace std;

class Player {
  public:
    Player() { cout << "Player created\n"; }
    ~Player() { cout << "Player destroyed\n"; } // Proof it deletes!
    void play() { cout << "Playing game...\n"; }
};

int main() {
    { // Create a scope
        // Create a unique_ptr using make_unique (Best Practice!)
        unique_ptr<Player> p1 = make_unique<Player>();
        
        p1->play(); // Use it exactly like a normal pointer
        
        // unique_ptr<Player> p2 = p1; // ERROR! Cannot copy a unique_ptr!
        
    } // SCOPE ENDS: p1 is destroyed, and it AUTOMATICALLY deletes the Player!
    
    cout << "Program ends\n";
    return 0;
}

5. std::sharedptr (Shared Ownership)

If multiple parts of your program need to point to the exact same data, use sharedptr. It keeps a Reference Count. Every time you copy the pointer, the count goes up. Every time a pointer is destroyed, the count goes down. When the count hits 0, it calls delete.
cpp
12345678910111213
int main() {
    shared_ptr<int> s1 = make_shared<int>(100);
    cout << "Count: " << s1.use_count() << endl; // Prints 1
    
    {
        shared_ptr<int> s2 = s1; // Allowed! Both point to 100.
        cout << "Count: " << s1.use_count() << endl; // Prints 2
    } // s2 goes out of scope. Count drops to 1.
    
    cout << "Count: " << s1.use_count() << endl; // Prints 1
    
    return 0;
} // s1 goes out of scope. Count drops to 0. Memory is DELETED!

6. std::weakptr (Breaking Cycles)

A weakptr is an observer. It points to memory managed by a sharedptr, but it does NOT increase the reference count.
  • Why use it? To prevent Cyclic References. If Object A has a sharedptr to Object B, and Object B has a sharedptr to Object A, their reference counts will never reach 0. They will keep each other alive forever (Memory Leak!). Using a weakptr for one of those links solves this.

7. Modern C++ Best Practices

  • Rule #1: Never use new or delete in modern C++ applications.
  • Rule #2: Default to std::uniqueptr for everything.
  • Rule #3: Only upgrade to std::sharedptr if you explicitly need shared ownership.

8. Memory-Level Explanation

Smart pointers are essentially small wrapper classes allocated on the Stack. Inside the wrapper is the raw pointer to the Heap memory. Because the wrapper is on the Stack, its Destructor is *guaranteed* to run when it goes out of scope (even during an Exception!). Inside that Destructor is the code that automatically calls delete on the raw Heap pointer.

9. Common Mistakes

  • Mixing raw pointers with smart pointers: int* raw = new int(5); uniqueptr<int> p(raw); This is dangerous if someone else deletes raw manually. Always use makeunique or makeshared.
  • Copying a uniqueptr: The compiler will prevent this. If you must transfer ownership, you must use std::move(ptr).

10. Exercises

  1. 1. Write a program using a std::uniqueptr to an array of 5 integers.
  1. 2. Demonstrate how a std::sharedptr tracks its reference count by printing .usecount() before and after a new scope block { }.

11. MCQ Quiz with Answers

Question 1

What is the main purpose of Smart Pointers?

Question 2

Which library is required to use smart pointers?

Question 3

Which smart pointer allows only one owner at a time?

Question 4

Can you copy a uniqueptr?

Question 5

How does a sharedptr know when to delete the memory?

Question 6

What function is best practice for creating a uniqueptr?

Question 7

Which smart pointer is used to observe a sharedptr without increasing its reference count?

Question 8

What problem does weakptr solve?

Q9. Do smart pointers guarantee exception safety? a) Yes, their destructors run during stack unwinding, automatically freeing memory b) No, memory still leaks during exceptions Answer: a) Yes, their destructors run during stack unwinding, automatically freeing memory

Q10. Is C++ natively garbage-collected like Java or C#? a) Yes b) No, it uses determinism (RAII) and smart pointers instead Answer: b) No, it uses determinism (RAII) and smart pointers instead

12. Interview Questions

  • Q: Explain RAII (Resource Acquisition Is Initialization) in C++ and how smart pointers utilize it.
  • Q: Describe a scenario where a cyclic reference causes a memory leak with sharedptr, and how to fix it.
  • Q: Why is std::makeshared preferred over std::sharedptr<T>(new T())? (Hint: Performance and single memory allocation).

13. Summary

Smart Pointers (unique
ptr, sharedptr, weakptr) modernize C++ by wrapping dangerous raw pointers in safe, stack-allocated classes. They automatically clean up memory when they go out of scope, eliminating memory leaks and making C++ as safe as garbage-collected languages, but with much better performance.

14. Next Chapter Recommendation

In Chapter 26: Lambda Expressions, we will explore another powerful C++11 feature: the ability to write quick, anonymous functions directly inside your code.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·