C++ Notes to Self: Shared Pointers

C/C++
‘std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer. Several shared_ptr objects may own the same object.’ [cppreference.com]
Author

Dennis Chua

Published

April 7, 2017


When programming in C++ there’s a geniune risk of forgetting to release dynamically allocated memory. To address this issue, the Standard Library promotes the idea of resource aquistion is initialization that underlies the use of smart pointers. C++11 provides three types of smart pointers. One of these is the shared pointer. We use a shared pointer whenever the underlying raw pointer it encapsulates needs to be accessed across several parts of the code.

#include <iostream>
#include <memory>

class MyInteger {
    public:
        int x {};

        void setValue(const int& val) {
            x = val;
        }

        const int getValue() const {
            return x;
        }
        
};

int main(int argc, char** argv) {
    std::shared_ptr<MyInteger> sp_01 {new MyInteger{}};
    std::cout << "sp_01 value: ";
    sp_01->setValue(500);
    std::cout << sp_01.get()->getValue() << std::endl;
    std::cout << "[sp_01 use count] " << sp_01.use_count() << std::endl;

    std::shared_ptr<MyInteger> sp_02 = sp_01;
    std::cout << "sp_02 value: ";
    std::cout << sp_02.get()->getValue() << std::endl;
    std::cout << "[sp_02 use count] " << sp_02.use_count() << std::endl;

    std::shared_ptr<MyInteger> sp_03 = sp_01;
    std::cout << "sp_03 value: ";
    std::cout << sp_03.get()->getValue() << std::endl;
    std::cout << "[sp_03 use count] " << sp_03.use_count() << std::endl;

    std::cout << std::endl << "Replacing common value to 1000" << std::endl;
    sp_01->setValue(1000);
    std::cout << "[sp_01 use count] " << sp_01.use_count() << std::endl;
    std::cout << "sp_01 value: ";
    std::cout << sp_01.get()->getValue() << std::endl;
    std::cout << "sp_02 value: ";
    std::cout << sp_02.get()->getValue() << std::endl;
    std::cout << "sp_03 value: ";
    std::cout << sp_03.get()->getValue() << std::endl;

    std::cout << std::endl << "Replacing underlying object with new MyInteger" << std::endl;
    sp_01.reset(new MyInteger{});
    sp_01->setValue(2432);
    std::cout << "sp_01 value: ";
    std::cout << sp_01.get()->getValue() << std::endl;
    std::cout << "[sp_01 use count] " << sp_01.use_count() << std::endl;
    std::cout << "sp_02 value: ";
    std::cout << sp_02.get()->getValue() << std::endl;
    std::cout << "[sp_02 use count] " << sp_02.use_count() << std::endl;
    std::cout << "sp_03 value: ";
    std::cout << sp_03.get()->getValue() << std::endl;
    std::cout << "[sp_03 use count] " << sp_03.use_count() << std::endl;

    std::cout << std::endl << "Resetting sp_02" << std::endl;
    std::cout << "Before reset sp_02 underlying pointer: ";
    std::cout << sp_02.get() << std::endl;
    sp_02.reset();
    std::cout << "After reset sp_02 underlying pointer: ";
    std::cout << sp_02.get() << "   (warning: null pointer)" << std::endl;
    std::cout << "[sp_02 use count] " << sp_02.use_count() << std::endl;
    std::cout << "sp_03 value: ";
    std::cout << sp_03.get()->getValue() << std::endl;
    std::cout << "[sp_03 use count] " << sp_03.use_count() << std::endl;

    return 0;
}

Listing for main.cpp.