#include <iostream>
#include <string>
#include <string_view>
#include <vector>
 
class Person
{
    int m_age{};
    std::string m_name{};
 
public:
    Person(int age, std::string_view name)
        : m_age{age}, m_name{name}
    {
        std::cout << "Creating person" << '\n';
    }
 
    ~Person()
    {
        std::cout << "Destroying person" << '\n';
    }
 
    void sayHello() const
    {
        std::cout << "Hi" << '\n';
    }
 
    friend std::ostream &operator<<(std::ostream &out, const Person &p)
    {
        return out << "Name: " << p.m_name << "\nAge: " << p.m_age << "\n";
    }
};
 
class SmartPointer
{
    Person *m_ptr{};
    std::vector<std::reference_wrapper<SmartPointer>> m_ptrs{};
 
public:
    SmartPointer(Person *ptr)
        : m_ptr{ptr} {}
 
    SmartPointer(SmartPointer &other)
    {
        m_ptr = other.m_ptr;
        other.m_ptr = nullptr;
        m_ptrs.push_back(other);
    }
 
    ~SmartPointer()
    {
        if (m_ptrs.empty())
        {
            delete m_ptr;
            return;
        }
 
        m_ptrs.back().get().m_ptr = m_ptr;
        m_ptrs.pop_back();
    }
 
    SmartPointer &operator=(SmartPointer &other)
    {
        if (this == &other)
            return *this;
 
        delete m_ptr;
 
        m_ptr = other.m_ptr;
        other.m_ptr = nullptr;
 
        return *this;
    }
 
    Person &
    operator*() const
    {
        return *m_ptr;
    }
 
    Person *operator->() const
    {
        return m_ptr;
    }
 
    operator bool()
    {
        return m_ptr != nullptr;
    }
};
 
void passByValue(SmartPointer ptr)
{
}
 
int main(int argc, char const *argv[])
{
 
    SmartPointer p{new Person(12, "Hemant")};
 
    {
        SmartPointer q{p};
    }
 
    std::cout << *p << '\n';
 
    p->sayHello();
    return 0;
}

References

  1. https://github.com/nitinsharmacs/cpp/tree/main/pointers/move-semantic.cpp