In C++, raw pointers have little to no use. No, not the concept of pointers/references, but raw pointers in C++. Why? Because they have been superseded by better, safer, more self-documenting alternatives. Let's start by looking at the uses for pointers in C:
That's the only uses for pointers in C that I am familiar with. A use you think is missing probably falls into one of those categories. So, what better alternatives replace pointers in C++?
In modern C++, that is, C++11 and C++14 (they're modern for now, who knows what C++17 will bring), the keywords
delete are never used. Never. You used to see them all the time in C++03, but now they are completely obsolete, so much so that code using one or the other is considered bad code. Pre-C++11 code using them is simply considered outdated.
Instead, there are the standard library smart pointer wrapper classes in the
std::shared_ptr. They are self-documenting, RAII-based, move-able objects which refer to dynamically allocated objects. They can be stored in containers, returned from functions, and constructed via
std::unique_ptr is what you will use a majority of the time, as it manages a dynamically allocated object by binding its lifetime to the scope of the
std::unique_ptr instance. They can be swapped and moved, and are guaranteed to free the resource they manage when they are destructed. They can even manage dynamically allocated arrays. A
std::vector<std::unique_ptr<T>> is much like a
boost::ptr_vector<T>. They cannot be copied, which is why they get their name - they uniquely reference an object.
std::shared_ptr is used much less often, as it is essentially a reference counter. Multiple instances may manage the same object, and the object is only freed when all instances have been destructed. They can be swapped, copied, moved, etc. and they even have a related class,
std::weak_ptr, which is a view to their managed object that does not affect the reference counter. Through a
std::weak_ptr you can see if the managed object still exists, and if it does, access it.
More info: http://en.cppreference.com/w/cpp/memory
In C, when a parameter, struct member, or any variable needs to be "optional" - that is, it may either have a value or not have a value, the solution was to use a pointer. If the pointer was null, the value did not exist. If the pointer is not null, dereferencing it gives you the value.
In modern C++, there will eventually be the
std::optional class (nearly identical to
boost::optional) which encapsulates this behavior in a safe way. It's not in C++ yet, unfortunately, but you can use Boost or replicate it yourself until then.
More info: http://en.cppreference.com/w/cpp/experimental/optional
In C, when you needed to access an object you did not own, you had to pass a pointer to it. In C++, not only are there references (which are aliases to objects), but there is also
std::reference_wrapper, which is a swappable, moveable, rebindable reference.
More info: http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper
In C, pointers would often be used for iteration of containers and buffers in memory. However, more complex containers like linked lists could not use the same interface for iteration. C++ actually solved this a long time ago when the popular Standard Template Library was absorbed into the C++ Standard Library almost unchanged, must like parts of Boost are now being absorbed into C++.
From the STL, the C++ Standard Library gained actual iterator classes and generic algorithms to work on sequences defined by start and end iterators. The iterators in C++ are so versatile that even raw pointers are valid iterators. There's different kinds of iterator and you can define your own, but all of them have in common the ability to access the iterator object, the ability to compare to another terator for equality and inequality, and the ability to iterate forward by one element.
The iterators in C++ are so powerful that many people forget that raw pointers are what they replace.
I actually forgot this one in the original version of this article. From C, functions are weird (like the C array type) and are not first-class citizens like most other types. To dynamically refer to different functions, C used function pointers. They have a convoluted syntax, though, and are limited because they aren't real functors; they are just pointers to a static function. Callbacks generally had a
void * parameter for user data.
C++11 gave us
std::bind, as well as lambdas, which allow for true functors and completely replace function pointers. Note: I don't count C++'s pointers-to-members as actual pointers.
More info: http://en.cppreference.com/w/cpp/header/functional
I don't really consider this a category for the original list at the top of this page because arrays are an abstract concept that C provided weird support for in the form of pointer objects and the strange array object type. Needless to say, the C++ Standard Library provides numerous container classes to use to represent arrays, the most commonly used one being
std::vector, which represents a contiguous random-access list (and not the dreaded
std::list as people often assume, which represents a linked-list, and is far less efficient 99% of the time).
Not only that, but as mentioned above, plain dynamically allocated arrays can be managed by both
std::shared_ptr, so even plain data buffers don't need raw pointers.
In my opinion, in C++, raw pointers are completely useless (or will be, when we get
std::optional). At least one of the alternatives I have mentioned above can and does replace any use for a pointer you may think of. If you think you have a use for a raw pointer that is not replaced by a better alternative in the standard library, feel free to email me as explained on the site index.
I mean that the C++ Standard Library classes use RAII, so no matter what path of execution your program takes, the standard library classes will properly clean up themselves when they go out of scope. This includes exceptions and early returns, the latter being very hasslesome in C and actually resulting in design patterns involving
goto. With RAII, you never need to worry about any of that nonsense, and you can focus on other things.
More info: https://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization