0

I have come across this simple code in a website. I didn't understand it fully. It would be very helpful for me if someone can breakdown the code line by line and explain.

This is a code for creating a template of a smart pointer (auto deletion of pointer is the main motto to create such a pointer)

#include <iostream>    
using namespace std;

template <class T>
class SmartPtr {
    T* ptr;

public:
    explicit SmartPtr(T* p = NULL) {
        ptr = p;
    }
    ~SmartPtr() {
        delete(ptr);
    }
    T& operator*() {
        return *ptr;
    }
    T* operator->() {
        return ptr;
    }
};

int main() {
    SmartPtr<int> ptr(new int());
    *ptr = 20;

    cout << *ptr;
    return 0;
}
Akira
  • 4,385
  • 3
  • 24
  • 46
  • 1
    I think SO is not the place to generic code-walk.However, I think there is a pretty good walkthrough here : [link](https://www.codeproject.com/Articles/15351/Implementing-a-simple-smart-pointer-in-c) – George Spatacean Jul 07 '17 at 09:31
  • Simply the template class SmartPtr owns the pointer of type T.When its deleting it will release(delete) the owned pointer. * and -> operator are overloaded so that we can use it as directly using the owned pointer. – user1438832 Jul 07 '17 at 09:31

2 Answers2

1

"Break down line by line" is a little bit excessive, for the future, try to mention single parts that you don't understand in particular. But since it's not that much code...

#include <iostream>
using namespace std;
template <class T> //make it a template in order to be able to store any type
class SmartPtr {
T *ptr; //wrapped pointer
public: explicit SmartPtr(T *p = NULL) { ptr = p; } //basic constructor

//delete pointer when the object dies.
//Note that this means that this is meant to be a unique pointer, 
//a shared pointer would have to count occurencies first
 ~SmartPtr() { delete(ptr); } 

//dereference operator to manipulate the content. 
//I prefer to go with T& instead of T & to make it clear that it is
//"reference of type T"
T & operator * () {  return *ptr; }
//bad operator which exposes the pointer itself.
//Make this const, like const T* operator -> () const { ... }
//else this could be used for the constructor again,
//leading to undefined behaviour when the pointer is deleted twice
T * operator -> () { return ptr; } }; //class ending brace at bad position

int main(){
SmartPtr<int> ptr(new int());
*ptr = 20;
cout << *ptr;
return 0; }
Aziuth
  • 3,652
  • 3
  • 18
  • 36
  • I dont understand the point "this could be used for the constructor again" . Please if you can elaborate it. – user1438832 Jul 07 '17 at 09:40
  • 1
    @user1438832 You could execute this code: `SmartPtr ptr(new int()); SmartPtr ptr2(ptr.operator->());` which would create two objects that wrap a pointer to the same position. When both run out of scope, both will call their destructor, deleting the pointer twice, which should never happen. The same happens when you copy your class, by the way. Like `SmartPtr ptr2 = ptr;`. You should adhere to the Rule of Three and implement copy constructor and assignment operator for that reason. Maybe simply delete those two. – Aziuth Jul 07 '17 at 10:17
  • @Aziuth thanks for the reply, I still have a small doubt, what does this piece of code do inside the main function `SmartPtr ptr(new int());` – Arvind Sharma Jul 07 '17 at 10:25
  • @ArvindSharma It creates a storage on the heap and passes a pointer to that storage to the constructor of SmartPtr, to wrap it. In smaller steps: `int* pointer_to_int = new int(); SmartPtr smart_pointer_to_int(pointer_to_int);`, although that obviously directly exposes the pointer that should be wrapped. – Aziuth Jul 07 '17 at 10:27
  • @ArvindSharma Question, did you ever worked with smart pointers? Because this is the basic smart pointer syntax. If you have trouble with this, begin with tutorial on how to use std::unique_ptr and std::shared_ptr. Makes no sense if you try to imitate them without having an idea how they are supposed to be used. – Aziuth Jul 07 '17 at 10:29
  • @Aziuth I came across this code as a part of my c++ basics learning. I know there exist predefined `smart_ptr` type. I just wanna explore the basics and learn more. – Arvind Sharma Jul 07 '17 at 10:30
  • @ArvindSharma Trying to imitate such things is not "basic learning". Especially if there is no text to explain it. Instead of learning *how* such things do stuff, learn *what* stuff they do. The *how* comes later. – Aziuth Jul 07 '17 at 10:31
  • @Aziuth Thanks for your advice – Arvind Sharma Jul 07 '17 at 10:34
  • @ArvindSharma If my answer or the other one by Akira satisfied your question, it would be nice if you accept one of them. – Aziuth Jul 07 '17 at 11:05
  • The *"leading to errors when the pointer is deleted twice"* is incorrect, deleting the same memory twice is **undefined behaviour**. Anyway, pointing out the weaknesses of the example in question, deserves an upvote. – Akira Jul 07 '17 at 12:43
  • @Akira You mean because of the definition of the word "error"? Since undefined behaviour could also result in wanted behaviour? That said, edited my answer accordingly. – Aziuth Jul 07 '17 at 15:22
  • @Aziuth, it was just a suggestion, because with undefined behavior anything may happen, including nothing. However, some compilers handle this as an error. – Akira Jul 07 '17 at 16:30
1

Your class SmartPtr encapsulates a pointer of type T and overloads the member access and dereference operators to allow access to the encapsulated pointer. Moreover it frees up the the allocated memory pointed by encapsulated pointer when its descructor is called.

Your class with commens:

template <class T>
class SmartPtr {
    T* ptr; // encapsulated pointer of type T

public:
    // constructor for SmartPtr class which assigns the specified pointer to the
    // encapsulated pointer
    explicit SmartPtr(T* p = NULL) {
        ptr = p;
    }
    // destructor for SmartPtr class which frees up the the allocated memory
    // pointed by the encapsulated pointer
    ~SmartPtr() {
        delete(ptr);
    }
    // overloads the dereference operator for SmartPtr class to allow syntax
    // like: *instance = value;
    T& operator*() {
        return *ptr;
    }
    // overloads the member access operator for SmartPtr class to allow syntax
    // like: instance->member();
    T* operator->() {
        return ptr;
    }
};

Usage of your SmartPtr class is show inside the main function you provided:

SmartPtr<int> ptr(new int());
*ptr = 20;

The first line does a class template instantiation and constructs an object (ptr) by calling the contructor with newly created int as parameter.

The second line calls the overloaded dereference operator and assigns value 20 to the encapsulated pointer. This line is equivalent to:

ptr.operator*() = 20;
Akira
  • 4,385
  • 3
  • 24
  • 46
  • Thank you for the reply. You have explained the driver function very well. As a beginner I actually understood your reply. – Arvind Sharma Jul 07 '17 at 10:33
  • You're welcome! Feel free to mark the good answers as useful and accept the one you think that answered your question. – Akira Jul 07 '17 at 10:49