I am surprised that more than 99% of the given examples are in fact fairly bad examples because in those cases dynamic allocation could be avoided
This is probably because the examples are intended to be super-simple.
So what could be good examples or uses for Smart Pointers in C++?
Never mind "goodness", but consider the following examples of cases where they're relevant:
1. When you can't hold on to the stack
template <typename T>
std::unique_ptr<T[]> print_and_allocate(std::size_t n)
{
std::cout << "Allocating " << n << " elements of size " << sizeof(T) << '\n';
return std::make_unique<T[]>(n);
}
you can't perform the allocation on the stack, because you're returning before your allocated element is used. Also, you can't just return a single constructed or an std::array
, because the number of elements to allocate is not known in advance.
2. A need to refer to one of several possible subclasses
class A;
class B : public A { /* ... */ };
class C : public A { /* ... */ };
// ...
auto my_a = std::unique_ptr<A>(condition ? (A*) new B : (A*) new C);
my_a.some_virtual_method();
3. Complex de-allocation logic
A pointer doesn't tell you when/how it needs to be freed/deallocated. You can make a simple assumption ("I need to free the pointer I get from this function"), but this already suggests expressing your assumption in a wrapper class. If the conditions for de-allocation are more complex, and especially if the pointer recipient isn't aware of them, it becomes critical that they be communicated somehow. An std::shared_ptr
or std::weak_ptr
are two ways to do so; and another is an std::unique_ptr
with a custom deleter.
4. When future usability not guaranteed
When the provider of the pointer can't guarantee it will continue to be valid, but expects that it likely will be - you need some kind of wrapper class to reflect that fact and to make sure you don't try to dereference the pointer when you actually can't. This is where std::weak_ptr()
comes into play.
More generally: If you needed to allocate memory and hold a pointer before, for some reason, and couldn't make do without it - you most-probably want to switch to using a smart pointer instead. See also:
What is a smart pointer and when should I use one (answer).