In this article, we will compare the C++11 Smart Pointer implementation shared_ptr
with a normal pointer.
Table of Contents
Missing ++, – – and [] operators in shared_ptr
While shared_ptr
in C++ offers robust memory management and facilitates collaborative ownership of resources, it intentionally lacks some operators that are available to raw pointers. This is primarily to prevent operations that could potentially compromise resource management or lead to undefined behavior.
- Dereference operator (
*
): Allows access to the resourceshared_ptr
is managing. - Member access operator (
->
): Enables calling of member functions on the resource.
Operators not provided by shared_ptr
- Pointer arithmetic (
+
,-
,++
,--
): Such operations onshared_ptr
could lead to mismanagement of the owned resource, as they would affect reference counting and resource ownership. - Subscript operator (
[]
):shared_ptr
is not designed to work with array types directly, hence it does not support direct subscript access.
Here’s a code example that illustrates the operators shared_ptr
supports and those it does not:
#include <iostream> #include <memory> struct Sample { void dummyFunction() { std::cout << "dummyFunction called" << std::endl; } }; int main() { std::shared_ptr<Sample> ptr = std::make_shared<Sample>(); // This will work: using the dereference operator to call dummyFunction (*ptr).dummyFunction(); // This will work: using the member access operator to call dummyFunction ptr->dummyFunction(); // These lines will not compile due to lack of support for these operators: // ptr[0]->dummyFunction(); // shared_ptr does not support subscript operator // ptr++; // shared_ptr does not support pointer arithmetic // ptr--; // shared_ptr does not support pointer arithmetic std::shared_ptr<Sample> ptr2 = ptr; // Copy constructor increments reference count // This will work: comparison operators are supported if (ptr == ptr2) { std::cout << "ptr and ptr2 are equal" << std::endl; } return 0; }
Output
dummyFunction called dummyFunction called ptr and ptr2 are equal
In this example, you can see how shared_ptr
allows for dereferencing and member access but disallows pointer arithmetic and array subscripting, unlike raw pointers. The comparison of two shared_ptr
instances is permitted, as it checks if they point to the same object.
Remember that while shared_ptr
does not natively support the subscript operator, you can still manage arrays safely using std::shared_ptr
by providing a custom deleter that calls delete[]
. However, for array management, C++17 introduced std::shared_ptr<T[]>
, which properly handles arrays without the need for a custom deleter.
Null Check with shared_ptr
Creating a shared_ptr
object without assigning it an initial value will result in an empty smart pointer.
Frequently Asked:
- Smart Pointer vs Raw Pointer in C++
- What is weak_ptr in Modern C++ & why do we need it?
- What is shared_ptr in C++?
- How not to use Smart Pointers in C++?
In contrast, an uninitialized raw pointer contains a garbage value, which may lead to undefined behavior if dereferenced, as there’s no inherent way to check if it points to a valid memory location or not.
With shared_ptr
, users can check for emptiness as follows:
#include <iostream> #include <memory> int main() { std::shared_ptr<int> ptr3; if (!ptr3) std::cout << "Yes, ptr3 is empty." << std::endl; if (ptr3 == NULL) std::cout << "ptr3 is empty." << std::endl; if (ptr3 == nullptr) std::cout << "ptr3 is empty." << std::endl; return 0; }
Output:
Yes, ptr3 is empty. ptr3 is empty. ptr3 is empty.
It’s also possible to access the internal raw pointer from a shared_ptr
object:
std::shared_ptr<Sample> ptr = std::make_shared<Sample>(); Sample* rawPtr = ptr.get();
While accessing the raw pointer is occasionally necessary, it should be done with caution. Manually deleting this pointer can lead to severe issues: when the shared_ptr
goes out of scope, it will attempt to delete the memory that has already been deleted, leading to undefined behavior and potential program crashes. This kind of problem underscores the importance of smart pointer use to manage lifetime and ownership clearly and safely.
In the next post, we will delve deeper into this topic and discuss best practices for using raw pointers in conjunction with smart pointers.
Summary
We learn about some of the differences between a raw pointer and smart pointer in C++