Code360 powered by Coding Ninjas X Naukri.com. Code360 powered by Coding Ninjas X Naukri.com
Table of contents
1.
Introduction
2.
Problems with Normal Pointers
3.
Smart Pointer
4.
Types of Smart Pointers
4.1.
Unique_ptr
4.2.
Shared_ptr
4.3.
Weak_ptr
5.
Summary
6.
Frequently Asked Questions
6.1.
What are smart pointers?
6.2.
How many types of smart pointers are there?
6.3.
What is the difference between smart pointers and normal pointers?
7.
Conclusion
Last Updated: Jul 25, 2024
Easy

Smart Pointers in C++

Author Gaurav Gandhi
0 upvote

Introduction

The address of another variable is stored in a pointer. Another way a pointer retrieves information from a resource that is not part of the program (heap memory). A copy of the resource is used, and any changes are made in the replicated version. Smart pointers are used to modify the content of the original resource. Smart Pointers are an abstract interface to actual pointers (also known as raw pointers), but they benefit from managing resources and clearing memory.

smart pointers in c++

Problems with Normal Pointers

The cuboid was created as a class with two data members (length, breadth, and height). A cuboid object is created dynamically by the method func().

The object p is destroyed after the method func() completes. Because we did not remove cu, the memory remains allocated, and other variables will not be able to access it.

We run an indefinite loop in main() that keeps generating p objects and allocating resources. Smart pointers are a solution to this problem, which turns out to be a memory leak.

Program:

#include <iostream>  
using namespace std;  
 
class Cuboid { // class Cuboid  
    private:  
        int length; // length of cuboid  
        int breadth; // breadth of cuboid  
        int height; // height of cuboid
};  
 
void func()
{  
    Cuboid* cu = new Cuboid(); // Create a dynamic object p  
}  
 
int main()  
{  
    // Infinite Loop  
    while (1) { // Run an infinite loop that will allocate p  
        func();  
    }  
}  

Smart Pointer

We'll utilize smart pointers to save up memory for resources that aren't being used. Create a class containing a pointer, destructors, and overloaded operators (->, *). When an object's scope expires, the destructor will be invoked automatically, and the dynamically allocated memory will be erased.

Program:

#include <iostream>  
using namespace std;  
 
class smartPointer { // class to implement smart Pointer  
    int* ptr; // Actual pointer  

    public:  
        // Explicit constructor  
        explicit smartPointer(int* x = NULL) {
            ptr = x;
        }  
   
        // Destructor  
        ~smartPointer() {
            delete (ptr);
        }  
   
        // Overloading dereferencing operator  
        int& operator*() {
            return *ptr;
        }  
};  
 
int main()  
{  
    smartPointer p(new int());  
    *p = 10;  
    cout << *p;  
    return 0;  
}  

 

Output:

10

 

Try and compile with online c++ compiler.

The preceding example only applies to integers. We'll make a template that works with any data type.

Program:

#include <iostream>  
using namespace std;  
 
template <class T> // template class  
class SmartPtr {  
    T* smartPointer; // Actual pointer  
public:  
    // Constructor  
    explicit SmartPtr(T* p = NULL) {
        smartPointer = p;
    }  
 
    // Destructor  
    ~SmartPtr() {
        delete (smartPointer);
    }  
 
    // Overloading dereferncing operator  
    T& operator*() {
        return *smartPointer;
    }  
 
    T* operator->() {
        return smartPointer;
    }  
};  
 
int main()  
{  
    SmartPtr<int> p(new int());  
    *p = 50;  
    cout << *p;  
    return 0;  
}

 

Output:

50

Types of Smart Pointers

Unique_ptr

A single item is stored in this sort of object. The current object is deallocated to attach a new one.

Program:

#include <iostream>  
#include <memory>  
using namespace std;  
 
 
class Cuboid { // Create the class  
    int length; // length of Cuboid  
    int breadth; // breadth of Cuboid
    int height;  
 
public:  
    Cuboid(int l, int b, int h)  // parameterised constructor
    {  
        length = l;  
        breadth = b;  
        height = h;
    }  
 
    int volume()  //Volume
    {  
        return length * breadth * height;
    }  
};  
 
int main()  
{  
 
    unique_ptr<Cuboid> cu1(new Cuboid(20, 5, 6));  
    cout << cu1->volume() << endl; // This will print the volume
   
    unique_ptr<Cuboid> cu2;  
    cu2 = move(cu1);  
 
    // This will print the volume  
    cout << cu2->volume() << endl;  
 
    return 0;  
}

 

Output:

600
600

Shared_ptr

More than one object can point to a single pointer in shared_ptr simultaneously. The use_count() function maintains a reference counter for designating the object.

Program:

#include <iostream>  
#include <memory>  
using namespace std;  
 
class Cuboid { // Create the class  
    int length; // length of Cuboid  
    int breadth; // breadth of Cuboid
    int height;  // height of Cuboid  
 
public:  
    Cuboid(int l, int b, int h)  // parameterised constructor
    {  
        length = l;  
        breadth = b;
        height = h;
    }  
 
    int volume()  
    { // calculate volume of Cuboid  
        return length * breadth * height; // return volume  
    }  
};  
 
int main()  
{  
 
    shared_ptr<Cuboid> cu1(new Cuboid(20, 5)); // create shared //ptr cu1  
    // volume will be printed
    cout << cu1->volume() << endl;  
    // Create shared ptr cu2  
    shared_ptr<Cuboid> cu2;  
    cu2 = cu1;  
 
    cout << cu2->volume() << endl;  
    cout << cu1->volume() << endl;
     
    cout << cu1.use_count() << endl;  
    return 0;  
}

 

Output:

600
600
600
2

Weak_ptr

The shared pointer is identical to weak_ptr. The distinction is that it doesn't keep a reference counter, and the object doesn't have a tight grip on the pointer. This attribute may cause a deadlock if many objects attempt to hold the reference. 

Summary

To wrap off this essay, I'll provide you with rules to follow while dealing with SMART pointers.

  • Whenever possible, attempt to utilize smart pointers. If you're not dealing with several pointers/threads sharing a memory address, use unique_ptr in most circumstances.
  • When dealing with numerous owners, utilize the reference-counted shared_ptr instead.
  • Use a weak_ptr if you wish to explore an object without requiring that the object exists. This pointer is useful for such jobs since it does not add to the reference count.
  • To decrease the overhead of utilizing smart pointers, make sure you only use raw pointers in a tiny amount of code or when you must use them.

Frequently Asked Questions

What are smart pointers?

A smart pointer is a wrapper class that manages dynamically allocated memory and ensures it is destroyed when the smart pointer object is no longer in use.

How many types of smart pointers are there?

There are three smart pointers types: unique_ptr, shared_ptr, and weak_ptr.

What is the difference between smart pointers and normal pointers?

A Smart Pointer is a wrapper class for a pointer with overloaded operators like * and ->. The smart pointer class's objects resemble regular pointers. It may, however, deallocate and release damaged object memory, unlike Normal Pointers.

Conclusion

In this article, we have extensively discussed how to utilize smart pointers in C++ and some instances of each.

We hope this blog has helped you enhance your knowledge regarding the smart pointers in the C++ language. If you would like to learn more, check out our articles on pointerslearn pointers, and pointers in C++

You can also practice coding questions commonly asked in interviews on Coding Ninjas Code360

Also, check out some of the Guided Paths on topics such as Data Structure and AlgorithmsCompetitive ProgrammingOperating SystemsComputer Networks, DBMSSystem Design, etc., as well as some Contests, Test Series, and Interview Experiences curated by top Industry Experts.

Live masterclass