Smart Pointer vs Raw Pointer in C++

In this article, we will compare the C++11 Smart Pointer implementation shared_ptr with a normal pointer.

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.

  1. Dereference operator (*): Allows access to the resource shared_ptr is managing.
  2. Member access operator (->): Enables calling of member functions on the resource.

Operators not provided by shared_ptr

  1. Pointer arithmetic (+, -, ++, --): Such operations on shared_ptr could lead to mismanagement of the owned resource, as they would affect reference counting and resource ownership.
  2. 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.

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++

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top