Raw Pointers


// As defined in C
int *p = new int();         //p is raw pointer.
        

Smart pointers

Automatically deletes the allocated memory when Object goes out of scope.
Allocate memory in ctr, Delete memory in dtr. Bcoz Destructors are automatically executed when Object goes out of scope.
Programmer may allocate memory using new() & later might forget to use delete().
Smart Pointer Implementation Example

template <class T>
class A{                    //This class is Smart pointer
    T *a;         //int *a;
public:
    A(T *r) : a(r) { cout << "Allocated\n"; }              //A(int *r):a(r)
    ~A(){
        delete a;
        cout << "Freed\n";
    }
    T &operator *(){        //int &operator *()    //& returns a only, does not create new copy
        return *a;
    }
};

int main(){
    //Automatic template type deduction => Provided in C++17
    A <int> obj(new int());	//obj is my pointer now. I can carry all pointer operations
    *obj = 10;
    cout << *obj;

    A  <float> obj1(new float());
}

# g++ smart_pointers
Allocated
10
Allocated 

Freed
Freed
        

Unique vs Shared pointer (Both are types of Smart Pointers)

Unique Shared
What Only 1 Owner of memory, ie only 1 pointer to an object Multiple owners of a resource
Copy Constructible No
There can be only one unique_ptr to any resource, any attempt to make a copy of a unique_ptr will cause a compile-time error.
unique_ptr<int> p(new int(5))       // Okay
unique_ptr<T> c = p;              // Error: Can't copy unique_ptr
Yes
shared_ptr <int> p   =   int* p   //We can think like this
shared_ptr <int> a(new int(2));
shared_ptr <int> b = a;  
Move Constructible Yes
unique_ptr<int> a(new int(5));
unique_ptr<T> b = std::move(a);     // Okay
Yes
Multiple pointers can point to same resource, Owner count is maintained using reference counting When none is referencing the memory, it's deleted automatically
shared_ptr <int> a(new int(2));
shared_ptr <int> b = std::move(a);
Creation Using make_shared Using make_shared

How shared_ptr is implemented internally?

shared_ptr maintains 2 things.
Creation of shared_ptr: reference_count=1
On every new shared_ptr creation: reference_count++
Deletion/Reset: reference_count--

int reference_count;
T* data;                  //and a pointer to the object being shared

template <typename T>
class shared_ptr {
    struct ControlBlock {   //stores a pointer to the object being shared (T* ptr_) and a reference count (int ref_count_).
        T* ptr_;
        int ref_count_;
    };    
    ControlBlock* data_;
public:
    shared_ptr(T* ptr) {
        data_ = new ControlBlock;
        data_->ptr_ = ptr;
        data_->ref_count_ = 1;
    }
    
    shared_ptr(const shared_ptr& other) {
        data_ = other.data_;
        data_->ref_count_++;
    }
    
    ~shared_ptr() {
        if (--data_->ref_count_ == 0) {
            delete data_->ptr_;
            delete data_;
        }
    }    
};