Which kind of pointers should I use in C++?

You should prefer the use of smart pointers in modern C++, more precisely, the unique pointer. Two major kinds of smart pointers are unique pointers and shared pointers. Both are declared inside the <memory>
header file and are available starting with C++11.
You should prefer smart pointers to raw pointers, as smart pointers are less prone to memory leaks. Smart pointers automatically destroy the object and deallocate the memory when they go out of scope.
First, let us look at the code that uses a raw pointer:
#include <iostream>
int main()
{
int* p = new int {123};
std::cout << "The pointed-to object is:" << *p << '\n';
delete p;
}
The above code should be replaced with the std::unique_ptr
pointer:
#include <iostream>
#include <memory>
int main()
{
std::unique_ptr<int> p = std::make_unique<int>(123);
std::cout << "The pointed-to object is:" << *p << '\n';
}
Notice the absence of any need for manual deletion when using a unique pointer. When the unique pointer goes out of scope, it will automatically:
- Destroy the pointed-to object.
- Deallocate the allocated memory.
Which smart pointer should I use, unique or shared?
Most of the time, you will be using the unique pointer. Unique pointers were meant as a replacement for raw pointers. Let's say that 90% of the time, you will be using a unique pointer, and 10% of the time, you will be using shared pointers.
What is the difference between a unique and shared pointer?
Only one unique pointer can point to an object, whereas multiple shared pointers can point to the same object. Unique pointer can not be copied, whereas shared pointers can be copied.
Raw vs. smart pointers
While it may not be possible to remove raw pointers from our framework completely, we should still aim to replace occurrences of raw pointers with smart pointers whenever possible.
For example, with raw pointers, we might forget to manually delete the pointer, which would cause a memory leak. With smart pointers, we don't have to worry about manual deletion, as they automatically perform cleanup when they go out of scope.
Examples
Using a unique pointer to dynamically allocate a space for a single integer (on heap):
std::unique_ptr<int> p = std::make_unique<int>(123);
Using a unique pointer to represent a data member of a class:
class MyClass
{
private:
std::unique_ptr<int> p;
// ...
};
A unique pointer to an object of a class:
std::unique_ptr<MyClass> p = std::make_unique<MyClass>(/* constructor arguments*/);
A polymorphic unique pointer to an object of a class:
std::unique_ptr<BaseClass> p = std::make_unique<DerivedClass>(/* constructor arguments*/);
How to initialize a unique pointer?
In C++11, you can initialize a unique pointer using the new
expression:
std::unique_ptr<int> p(new int{ 123 });
In C++14 and above, you should use the std::make_unique
function to initialize a unique pointer:
std::unique_ptr<int> p = std::make_unique<int>(123);
Summary:
Prefer smart pointers (mainly the unique pointer) over raw pointers in modern C++ as they are less prone to memory leaks.