Disclaimer: This is post is just showing example smart pointer implementations for illustrative purposes. In production code I would recommend using the standard library unique_ptr and shared_ptr instead.
A basic smart pointer will wrap a pointer, so the object gets destroyed that when the pointer goes out of scope. This is particularly useful if there are returns in nested if statements or there are exceptions. We don’t need to have separate delete’s in every possible exit path. Here is a basic implementation:
I’ve left out a few things to keep it simple, such as move semantics (which we probably want to disable move constructor and move assignment).
If we want to use multiple pointers to refer to the same object, we can use a shared pointer. In the standard library this is called shared_ptr. It is implemented by reference counting. So each pointer that points to the same object also has a shared reference count, which is incremented when a new copy of the pointer is created and decremented when a copy of the pointer is deleted. When the count goes to zero, we delete the object and reference count. Here is the general idea of how this is implemented:
Again, there are some things left out to keep it simple, e.g. move semantics and using the copy & swap idiom.