#include <iostream>
using namespace std;

template<typename T> // because of using the template we can actually use any data type of your choice so this is generic
class uniqueptr{

private:
  T *res; // it will have the same size as of the raw pointer . there will be no increase in size beecause of unique ptr

public:
   uniqueptr(T *val=nullptr) : res(val){
       cout<<"construtcor is called\n";
   }

   //uniqueptr(const uniqueptr<T> &ptr ) = delete; //compiler will write anything over here. if anything comes it will delete // copy constructor
   //uniqueptr& opertaor=(const uniqueptr<T> &ptr ) = delete; //copy assignmenet operator
  
   uniqueptr(const uniqueptr<T> &&ptr ) // move constructor . why &&? when we do this we will be sending a R value . when we write move(ptr1) it will change the ptr1 as R value and capture by thi sstatement. 
   {
      res = ptr.res;  // ptr 1 resource will move to the ptr 3 resource
      ptr.res = nullptr;  // now we need to delete the old ptr as we have completely trasfereed and now we need to point to null, transfer the owenership
   }

   uniqueptr& operator=(const uniqueptr<T>&& ptr) //move assignment opertator
   {
       if(this->res != &res) // to check whteher it is not pointing to the same thing ---> this why we need to do . if someone tries to do this ptr4=ptr4 , means already there is a resourse so we need to make sure we need to delete this or not
       {
           if(res)  // also before deleting we are making sure that prev one which is there that we are deleting before assigning
            delete res; 
           
           res = ptr.res;
           ptr.res = nullptr;
      }
       return *this;
   }

  T* operator->() // actually returninng the raw pointer so thats why T*
  {
    return res;
  }

  T& operator*() //thhis is returning the value of the pointer so the resturn type is & as we are returing *res by derefeing it so &will hold it
  {
    return *res; //as we are returing * thats why the & is the return type;
  }

   T* get()
   {
     return  res; // returning the raw pointer 
   }

   //with reset deallocate the prev value and allocate with the new value
   void reset(T* newres)
   {
      if(res)
      {
          delete res;
      }

       res=newres;
   }

   ~uniqueptr()  //destructor
   {
     if(res)
      {
          delete res;
          res=nullptr;
      }

   }
    
};


int main() {

    uniqueptr<int> ptr1(new int(10));
    //uniqueptr<int> ptr2(ptr1); //this will give compilation error as it should transfer the complete ownership 
    //uniqueptr<int> ptr3(ptr1); // compilation error
    //uniqueptr<int> ptr4(new int(40));
    //ptr4 = ptr3; // compilation error  //copy assignment operator

    // to transfer the ownershop we use move
    uniqueptr<int> ptr3 = move(ptr1);
    uniqueptr<int> ptr4(new int(40));
    ptr4 = move(ptr3);

    // we need to see what else we do with pointers , we print it out, we dereferenced, we use to call another fucntion
    //ptr1->func(); // impement the -> fucntion 
    cout<< *(ptr4); // implement the * operator 
    ptr1.get(); // it will get us the actuaal raw pointer what we are handling
    ptr1.reset(new int(20)); //if i am handling one resource and i need to handle another resourse then we reset it using this func. prev one will be deleted and this will be used.

    //destructor
    //however we use the normal pointer we can use the smart pointers
    return 0;
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: