Courses/C++/Move Semantics & Smart Pointers

    Lesson 14 • Expert

    Move Semantics & Smart Pointers

    Eliminate manual memory management with unique_ptr, shared_ptr, weak_ptr, and understand move semantics for zero-cost resource transfers.

    What You'll Learn

    • unique_ptr for exclusive ownership
    • shared_ptr and weak_ptr for shared ownership
    • Move constructors and move assignment
    • std::move and rvalue references

    Why Smart Pointers?

    In the previous lesson, you saw how raw new/delete can cause leaks and crashes. Smart pointers wrap raw pointers and automatically call delete when they go out of scope. Think of them as pointers with a built-in "self-destruct" — no more forgetting to free memory.

    TypeOwnershipUse Case
    unique_ptrSingle ownerDefault choice — 95% of cases
    shared_ptrMultiple ownersShared resources, caches
    weak_ptrNon-owning observerBreaking circular references

    unique_ptr — Exclusive Ownership

    Create, transfer, and auto-delete resources with unique_ptr

    Try it Yourself »
    C++
    #include <iostream>
    #include <memory>
    using namespace std;
    
    class Player {
        string name;
        int health;
    public:
        Player(string n, int h) : name(n), health(h) {
            cout << name << " created" << endl;
        }
        ~Player() {
            cout << name << " destroyed" << endl;
        }
        void takeDamage(int d) {
            health -= d;
            cout << name << " took " << d << " damage. HP: " << health << endl;
        }
        string getName() const { return name; }
    };
    
    int main() {
        // unique_ptr — so
    ...

    shared_ptr & weak_ptr

    Share ownership and observe resources without extending lifetime

    Try it Yourself »
    C++
    #include <iostream>
    #include <memory>
    using namespace std;
    
    class Resource {
        string name;
    public:
        Resource(string n) : name(n) {
            cout << "Resource '" << name << "' acquired" << endl;
        }
        ~Resource() {
            cout << "Resource '" << name << "' released" << endl;
        }
        void use() { cout << "Using " << name << endl; }
    };
    
    int main() {
        cout << "=== shared_ptr: Shared Ownership ===" << endl;
        
        shared_ptr<Resource> r1 = make_shared<Resource>("Database");
        cout 
    ...

    Move Semantics — Steal, Don't Copy

    Copying a million-element vector means duplicating a million elements — expensive. Moving transfers the internal pointer from source to destination in constant time. The source becomes empty but valid.

    Think of moving house: instead of photocopying every item (copy), you drive the moving truck to the new address (move). Same stuff, zero duplication.

    string a = "Hello";
    string b = move(a);   // b steals a's buffer
    // a is now "" (valid but empty)
    // b is "Hello" — no characters were copied

    Move vs. Copy

    Compare expensive copy with cheap move operations

    Try it Yourself »
    C++
    #include <iostream>
    #include <vector>
    #include <string>
    using namespace std;
    
    class BigData {
        vector<int> data;
        string label;
    public:
        BigData(string l, int size) : label(l), data(size, 42) {
            cout << label << " constructed (" << size << " ints)" << endl;
        }
        
        // Copy constructor (expensive)
        BigData(const BigData& other) : data(other.data), label(other.label + "_copy") {
            cout << label << " COPIED (expensive!)" << endl;
        }
        
        // Move constructor (c
    ...

    Common Mistakes

    ⚠️ Using object after move: After std::move(x), x is in a valid but unspecified state. Don't read its value.

    ⚠️ Copying unique_ptr: unique_ptr cannot be copied. Use std::move to transfer ownership.

    ⚠️ Circular shared_ptr: Two objects with shared_ptr to each other will never be freed. Break cycles with weak_ptr.

    ⚠️ Using new with smart pointers: Prefer make_unique and make_shared — they're exception-safe and more efficient.

    Pro Tips

    💡 Default to unique_ptr: Start with unique_ptr and only upgrade to shared_ptr if you genuinely need shared ownership.

    💡 Mark move ops noexcept: Move constructors should be noexcept so STL containers can use them during reallocation.

    💡 Rule of Five: If you write any of destructor, copy constructor, copy assignment, move constructor, or move assignment — write all five.

    📋 Quick Reference

    OperationSyntax
    Create unique_ptrauto p = make_unique<T>(args);
    Create shared_ptrauto p = make_shared<T>(args);
    Transfer ownershipauto b = move(a);
    Check nullif (ptr) or if (!ptr)
    Reference countptr.use_count()
    Weak lockif (auto sp = weak.lock())

    Lesson Complete!

    You now know how to use smart pointers and move semantics to write safe, efficient C++. Next, you'll dive deeper into the C++ Memory Model — understanding how the compiler and CPU manage memory at a low level.

    Sign up for free to track which lessons you've completed and get learning reminders.

    Previous

    Cookie & Privacy Settings

    We use cookies to improve your experience, analyze traffic, and show personalized ads. You can manage your preferences below.

    By clicking "Accept All", you consent to our use of cookies for analytics and personalized advertising. You can customize your preferences or reject non-essential cookies.

    Privacy PolicyTerms of Service