Skip to content

C++ Smart Pointers

Overview

Smart pointers are objects that manage memory automatically and help prevent memory leaks and dangling pointers.

unique_ptr

Exclusive Ownership

cpp
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource created" << std::endl; }
    ~Resource() { std::cout << "Resource destroyed" << std::endl; }
    void doSomething() { std::cout << "Doing something" << std::endl; }
};

int main() {
    // Create unique_ptr
    std::unique_ptr<Resource> ptr = std::make_unique<Resource>();
    ptr->doSomething();
    
    // Transfer ownership
    std::unique_ptr<Resource> ptr2 = std::move(ptr);
    
    if (!ptr) {
        std::cout << "ptr is null after move" << std::endl;
    }
    
    ptr2->doSomething();
    
    // Resource is automatically destroyed when ptr2 goes out of scope
    
    return 0;
}

shared_ptr

Shared Ownership

cpp
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource created" << std::endl; }
    ~Resource() { std::cout << "Resource destroyed" << std::endl; }
    void doSomething() { std::cout << "Doing something" << std::endl; }
};

int main() {
    // Create shared_ptr
    std::shared_ptr<Resource> ptr1 = std::make_shared<Resource>();
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;
    
    {
        std::shared_ptr<Resource> ptr2 = ptr1;
        std::cout << "Reference count: " << ptr1.use_count() << std::endl;
        ptr2->doSomething();
    }  // ptr2 goes out of scope
    
    std::cout << "Reference count: " << ptr1.use_count() << std::endl;
    
    return 0;
}

weak_ptr

Non-owning References

cpp
#include <iostream>
#include <memory>

class Node {
public:
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;  // Use weak_ptr to avoid circular reference
    
    ~Node() { std::cout << "Node destroyed" << std::endl; }
};

int main() {
    auto node1 = std::make_shared<Node>();
    auto node2 = std::make_shared<Node>();
    
    node1->next = node2;
    node2->prev = node1;  // weak_ptr doesn't increase reference count
    
    std::cout << "node1 use_count: " << node1.use_count() << std::endl;
    std::cout << "node2 use_count: " << node2.use_count() << std::endl;
    
    // Access weak_ptr
    if (auto locked = node2->prev.lock()) {
        std::cout << "Previous node exists" << std::endl;
    }
    
    return 0;
}

Content is for learning and research only.