Smart Pointers In C++ - C++ Programming Tutorial
C++ Course / Pointers & References / Smart Pointers In C++

Smart Pointers In C++

BLUF: Mastering Smart Pointers In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Smart Pointers In C++

C++ is renowned for its efficiency. Learn how Smart Pointers In C++ enables low-level control and high-performance computing in the tutorial below.

In C++, smarcpp tutorialers refer to class templates available in the standard library (<memory>) designed to handle dynamic memory allocation automatically. They serve as abstractions over raw pointers, offering enhanced memory management capabilities. These pointers are typically utilized as templates, allowing us to create smarcpp tutorialers for various memory types.

Smarcpp tutorialers help to prevent several general memory issues in C++ programming . Some issues are as follows:

  • Memory leaks
  • Dangling pointers
  • Double deletion
  • Unmanaged resources

Smarcpp guides adhere to the RAII (resource acquisition initialization) principle, ensuring that memory is automatically acquired and released. Our implementation of smarcpp tutorials will include the automatic release of unused resources' memory. Initially, we need to define a class containing a pointer, overloaded operators (->, *), and destructors. Subsequently, the destructor will be invoked automatically upon the object exiting the scope, facilitating the automatic deletion of dynamically allocated memory.

Smart Pointers Example in C++

Let's consider an example to demonstrate the usage of the smarcpp tutorial in C++.

Example

Example

#include <iostream>  

using namespace std;    //using standard namespace

class SmartPtr { // Create the class to implement smart Pointer  

    int* ptr; // Actual pointer  

public:  

// Create an explicit constructor   

    explicit SmartPtr(int* p = NULL) { ptr = p; }  

      // Destructor to deallocate the resource used   

    ~SmartPtr() { delete (ptr); }  

      // Overloading dereferencing operator  

    int& operator*() { return *ptr; }  

};  

  int main()    //main function

{  

    SmartPtr ptr(new int());  

    *ptr = 100;  

    cout << *ptr;  

      // We don't need to call delete ptr: when the object  

    // ptr goes out of scope, the destructor for it is automatically  

    // called, and destructor does delete ptr.  

    return 0;  

}

Output:

Explanation:

In this instance, we showcase a smarcpp guide employing a personalized SmartPtr class. This class handles a dynamically allocated integer and ensures memory deallocation through its destructor, effectively avoiding memory leaks. Furthermore, the * operator overload grants access to the pointed value akin to a standard pointer.

Smart Pointer Example in C++ using Template Class

The previous instance is tailored specifically for integers. Next, we will devise a generic template that can accommodate any data type. To exemplify this concept, we will delve into a smarcpp tutorial in C++ by employing a template class.

Example

Example

#include <iostream>  

using namespace std;     //using standard namespace

  template <class T> // Create a template class   

class SmartPtr {  

    T* ptr; // Actual pointer  

public:  

    // Constructor  

    explicit SmartPtr(T* p = NULL) { ptr = p; }  

      // Destructor  

    ~SmartPtr() { delete (ptr); }  

    // Overloading dereferencing operator  

    T& operator*() { return *ptr; }  

    // Overloading arrow operator so that  

    // members of T can be accessed  

    // like a pointer

    T* operator->() { return ptr; }  

};  

int main()    //main function

{  

    SmartPtr<int> ptr(new int());  

    *ptr = 100;  

    cout << *ptr;  

    return 0;  

}

Output:

Explanation:

In this instance, we introduce a general tutorialer class named SmartPtr implemented with C++ templates, facilitating the handling of dynamically allocated objects across various types. Consequently, its destructor handles the automatic resource deletion, effectively mitigating potential memory leakage. By leveraging the overloaded * and -> operators, users can simulate pointer functionality to access and update the object.

Types of Smart Pointers

There are multiple smarcpp guides available in C++. A few examples are listed below:

Unique_ptr

The uniqueptr serves as a smart pointer in C++ that guarantees exclusive ownership of a particular resource, preventing memory leaks and ensuring consistent behavior. This pointer signifies that the linked resource will be automatically released upon uniqueptr going out of scope or when explicitly transferred using the move function.

Syntax:

It has the following syntax:

Example

std::unique_ptr<Type> ptr(new Type(args));

Features of Unique_ptr in C++

Several features of unique_ptr in C++ are as follows:

  • It particularly owns a resource.
  • It cannot be copied, only transferred.
  • When a unique_ptr is out of scope, it automatically removes the object.

Unique_ptr Example in C++

Let's consider a scenario to demonstrate the Unique_ptr usage in C++.

Example

Example

#include <iostream>  

#include <memory>  

using namespace std;    //using standard namespace

    class Rectangle { 

    

    int length; // length of rectangle   

    int breadth; // breadth of rectangle   

  public:  

    Rectangle(int l, int b)  

    { // parameterised constructor  

        length = l;  

        breadth = b;  

    }  

     int area()  

    { // calculate area  

        return length * breadth; // return the area   

    }  

};  

  int main()    //main function

{  

    unique_ptr<Rectangle> P1(new Rectangle(20, 5));  

    cout << P1->area() << endl; // This print 100  

    // unique_ptr<Rectangle> P2(P1);  

    unique_ptr<Rectangle> P2;  

    P2 = move(P1);  

    

   cout << P2->area() << endl;    

    return 0;  

}

Output:

Output

100

100

Explanation:

In this instance, we illustrate how unique_ptr handles dynamic memory allocation for a Rectangle entity. The transfer of pointer ownership from P1 to P2 is facilitated through the move method, guaranteeing exclusive ownership by a single unique pointer at any given moment. Subsequently, the area is retrieved utilizing the arrow operator.

Shared_ptr

In the sharedptr, it is possible to assign multiple objects to a single pointer simultaneously. A reference count is kept track of to indicate the number of objects referencing the pointer through the usecount function.

Syntax:

It has the following syntax:

Example

std::shared_ptr<Type> ptr = std::make_shared<Type>(args...);

Features of the shared_ptr function in C++

Several features of the shared_ptr function in C++ are as follows:

  • It allows a shared ownership of a resource.
  • It uses reference count internally.
  • When the last shared_ptr is destroyed, the memory is removed.

Shared_ptr Example in C++

Let's consider an instance to demonstrate the shared_ptr in C++.

Example

Example

#include <iostream>  

#include <memory>  

using namespace std;  //using standard namespace

class Rectangle {

    int length;

    int breadth;

public:

    Rectangle(int l, int b) {

        length = l;

        breadth = b;

    }

    int area() {

        return length * breadth;

    }

};

int main() {   //main function

    shared_ptr<Rectangle> P1(new Rectangle(20, 5));  // Create shared_ptr P1

    cout << P1->area() << endl;

    shared_ptr<Rectangle> P2;  // Create shared_ptr P2

    P2 = P1;  // Now both P1 and P2 point to the same object

    cout << P2->area() << endl;

    // Both P1 and P2 are valid shared_ptrs to the same Rectangle

    cout << P1->area() << endl;

    // Reference count (use_count) will be 2

    cout << P1.use_count() << endl;

    return 0;

}

Output:

Output

100

100

100

2

Explanation:

In this instance, we showcase the utilization of sharedptr in the C++ programming language. Initially, we have instantiated two smart pointers (P1 and P2) that jointly hold ownership of a Rectangle instance. Subsequently, both pointers have the capability to invoke the area function and the usecount method, which indicates the number of pointers currently handling the object.

Weak_ptr

The weakptr behaves similarly to the shared pointer. One key contrast between weak and sharedptr is that it does not keep track of a reference count, and there is no strong ownership of the object by the pointer. This characteristic can potentially lead to a deadlock situation as multiple objects may attempt to retain the pointer.

Syntax

It has the following syntax:

Example

std::weak_ptr<Type> wp = sp;

Features of weak_ptr in C++

Several features of the weak_ptr in C++ are as follows:

  • Non-owner reference to a common shared resource.
  • It is used to break the circular references that can occur when one and multiple shared_ptr instances reference each other, which helps to prevent memory leaks.
  • It does not affect the reference count.

Weak_ptr Example in C++

Let's consider an example to demonstrate the functionality of the weak_ptr in C++.

Example

Example

#include <iostream>

#include <memory>

using namespace std;  //using standard namespace

class Child;

class Parent {

public:

    shared_ptr<Child> child;

    ~Parent() {

      cout << "Parent destroyed\n";

    }

};

class Child {

public:

    weak_ptr<Parent> parent;  // Weak reference to avoid circular dependency

    ~Child() {

        cout << "Child destroyed\n";

    }

};

int main() {   //main function

    {

        shared_ptr<Parent> p = make_shared<Parent>();

        shared_ptr<Child> c = make_shared<Child>();

        p->child = c;

        c->parent = p; // Only weak_ptr here avoids memory leak

        cout << "Parent use count: " << p.use_count() << endl;

        cout << "Child use count: " << c.use_count() << endl;

    }

    cout << "End of scope reached.\n";

    return 0;

}

Output:

Output

Parent use count: 1

Child use count: 1

Child destroyed

Parent destroyed

End of scope reached.

Explanation:

In this instance, we showcase the use of weakptr to prevent circular references. In this scenario, the Parent class retains a sharedptr pointing to the Child class, whereas the Child class maintains a weakptr pointing to the Parent class. This setup guarantees that when both classes are no longer in use, their destructors are invoked correctly, thereby avoiding memory leaks stemming from cyclic sharedptr dependencies.

Differences between Raw pointers and Smarcpp tutorialers in C++

Several variances between Raw pointers and smart pointers in C++ are outlined below:

Features Raw Pointer (*) Smart Pointer (std::uniqueptr, std::sharedptr, etc.)
Memory Management It has manual management, and must use new and delete. It has automatic memory management. It means that the memory is managed and released when no longer needed.
Ownership Semantics No ownership tracking Ownership is well-defined (unique, shared, or weak)
Risk of Memory Leaks There is a high risk of memory leaks because the use must remember to manually delete any dynamically allocated memory There is a low risk of memory leaks because the managed memory is automatically deallocated.
Dangling Pointers Possible if deleted too early Reduced chance due to scope-based destruction
Copying Behavior Freely copyable Depends on type (uniqueptr is non-copyable, sharedptr is copyable)
Thread Safety It is not inherently thread-safe. shared_ptr is thread-safe for reference count; others may not be.
Syntax Complexity It has simple syntax. It is slightly more verbose (e.g., std::makesharedPRESERVE12__()).
Support for Custom Deleters Manual deletion only It supports custom deleters (especially with unique_ptr).
STL Compatibility It is not safe to use with containers. It is designed to work well with STL containers.
C++ Version Requirement It is available in all C++ versions. It requires C++11 or later.

Conclusion

In summary, C++ smart pointers streamline memory management tasks by taking care of resource allocation automatically. They play a crucial role in preventing common problems like memory leaks, dangling pointers, and the need for manual deletion calls. Smart pointers like std::uniqueptr, std::sharedptr, and std::weak_ptr cater to distinct ownership needs, supporting the RAII principle for writing safer and easier-to-maintain code. These smart pointers are essential in contemporary C++ development for promoting tidy and effective memory utilization. Embracing smart pointers results in more robust and bug-free software applications.

Smart Pointers MCQs

1) What happens if we try to copy a std::unique_ptr in C++?

  • The program compiles and works as expected
  • The object has been duplicated
  • A compilation-time error occurs
  • A runtime exception is thrown

2) What is the main advantage of using smarcpp tutorialers over raw pointers in C++?

  • They increase the size of the program
  • They help prevent memory leaks
  • They require manual memory management
  • They slow down the code

3) Why is std::unique_ptr preferred for single ownership of a resource in C++?

  • It ensures special ownership and automatic deletion
  • It supports copying
  • It allows shared access
  • It turns off dynamic memory

a) It guarantees unique ownership and automatic removal

4) How does std::shared_ptr manage the lifetime of a resource in C++?

  • It immediately removes resources
  • It uses manual deletion
  • It removes resources when the final shared_ptr is destroyed
  • It never removes resources

5) What happens when a uniqueptr is moved to another uniqueptr?

  • Both point to the same resource
  • The original pointer is copied
  • nothing happens
  • Ownership is transferred; the original becomes null

Ownership is shifted, rendering the original object as null.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience