#include <iostream>
using namespace std;

template<typename T>
class sharedptr{

 private:
   T *res;
   T *counter;

 void incrementcounter()
 { 
    if(counter)
    {
       (*counter)++;
    }
 }

 void decrementcounter()
 { 
    if(counter)
    {
       (*counter)--; now while decrementing the counter what if counter become zero then we need delte it .

        if(*(counter) == 0) // here we check if the counter is zero we will delete the resource and counter
           {
             if(res) //just to check if there is any res
             {
                 delete res;
                 delete counter;
                 res = nullptr;
             }
           }
    }
 }

 public:
   shareptr(T* ptr=nullptr) : res(ptr) , counter(new int(1)) // means everytime somebody calls we calls counter is taken as 1
   {
        cout<<"constructor called"; 
   }

  shareptr<T>(const shareptr<T>& ptr) //now copy construtor will come when we write this. 2 resource will point to same place
  {
     res=ptr.res; //both ptr2 nd ptr3 is pointing to the same resource 
     couunter = ptr.counter; // similarly with counter, whatever pointing to the ptr counter same is pointing to current counter
     incrementcounter(); // and also we need to increment the counter so for that we need to call a function which we will declare in private scope. cz no other member needs to use it
                          // as we need the fucntion is other places also we need also have multiple statement so we use a sepatrate fcuntion
      
  }

  //when we do ptr3=ptr2 so ptr2 is pointing to some resource and ptr3 is pointing to some other resource now we need to make them point to same resource
  // so basically for this we need to decrement the pointer for ptr3 and point to ptr2 and then increment the counter

  shareptr<T>& operator=(const shareptr<T>& ptr) //copy assignment operator
  {
      if(this != &ptr)
      {
          decrementcounter(); //as all the checks are happening within the function so we no need to write it here
                              // supoose after decrementing this object was the only one pointing to that resource counter would have become 0 so we delte that resource

          res = ptr.res;
          counter = ptr.counter; // now whatever ptr counter came it will point to same counter.
          incrementcounter(); // no we increment the counter
      }
      return *this;
  }


 shareptr<T>(shareptr<T> && ptr) // move copy construtcor , here we dont need const cz we are changing the ptr itseelf
 {
    res = ptr.res;  // ptr will point to res
     counter = ptr.counter; //counter will point to this counter
     //we take the whole resource and pass to another and current to null. but do we need increment counter??
     //no , the counter is same because earlier another pointer was coming so we were incrementing the counter
     // but here there is totally a new pointer where we transfer the ownership so we need the same count as prev counter

     ptr.res = nullptr;
     ptr.counter = nullptr;    
 }

 shareptr<T>& operator=(shareptr<T>&& ptr) //move copy assignment operator
  {
    if(this != &ptr)
      {
         decrementcounter(); // decrement the counter because now we will be pointing to something else this which was pointing to we have to decrememt
                             // cz in case of constructor we dont point to somthing but as it is copy assignment we are already pointing to something so we need to decrememt
          res = ptr.res;
          counter = ptr.counter; // here new pointer is pointing to where old ptr was pointing and old one we make it null cz we are trasfering
          ptr.res = nullptr;
          ptr.counter = nullptr;
      }
    return *this;
  }


 void reset(T* ptr) // one obj is already trying to point to something now we are trying to reset to some other new resource
 {
      decrementcounter(); //as this obj is already pointing now this will be leaving the what it points to . so we neeed to decrement the counter 
     res= ptr.res; // then pouint to new res , so it need to create a counter all toghether it cannot use the same counter 
     counter = new int(1); // so we are reseting the counter to 1 . this is new fresh one
 }

 int get_count()
 {
      if(counter)
      {
          return (*counter);
      }

     return -1;
 }

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

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

 T* get()
 {
    return res;   
 }

 ~shareptr() // when this ptr goes out of scope so whatever the this object is pointing the resource to it should decrement the count not delete it
 {           // cz it might be pointed out by some other obj. 
    decrementcounter(); // so inside decrementcounter function it will take care in a sense means if its a last ptr when count becomes 0 then it should delete it
 }

};

int main() {

    shareptr<int> ptr1; //default constructor
    shareptr<int> ptr2(new int(10)); //param constructor
    shareptr<int> ptr3(ptr2); //copy const
    shareptr<int> ptr4(new int(40)); //copy assignment operator
    ptr4 = ptr3;
    sharedptr<int> ptr4(move(ptr1));//ownership is transferrred from ptr1 to the new ptr that is ptr4 . how this gets implemented . this gets implemented using move copy constructor.
    ptr2 = move(ptr3); //move copy assignment operator 

    APIs that can be used 

    ptr1.reset(); it will reset to null
    ptr1.reset(new int(5)); // it will reset with some resource.

    ptr1->func(); // implementing -> operator
    cout<<*ptr1; //inplementing * operator 

    ptr1.get() // it returns the raw pointer

    //here we need to implmenet one more thing which was not present in unique ptr

    ptr1.get_count() //shared ptr will be use for  multiple resources so get count api is implemented. no of object pointing to the same resoource

    
    
    return 0;
}

Embed on website

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