std::shared_ptr

std::shared_ptr for shared ownership
  • An object accessed via std::shared_ptrs has its lifetime managed by those pointers through shared ownership.
  • No specific std::shared_ptr owns the object.
  • Instead all shared_ptr’s pointing to it collaborates to ensure its destruction at the point where it’s no longer needed.
  • When the last shared_ptr pointing to an object stops pointing there, that shared_ptr destroys the object it points to.
  • A shared_ptr can tell whether it’s the last one pointing to a resource by consulting the resource’s reference count, a value associated with the resource that keeps track of how many shared_ptrs point to it.
  • Shared_ptrs constructors increments this count
  • shared_ptrs destructors decrements it and copy assignment operators do both. If sp1 and sp2 are shared_ptrs to different objects, the assignment “sp1=sp2” , modifies sp1 such that it points  to the object pointed to by sp2. sp1 reference count is decremented, while that for the object pointed to by sp2 is incremented.
  • std::shared_ptrs are twice the size of raw pointer – Because they internally contain a raw pointer to the resource as well as a raw pointer to the resource’s reference count(pointing to the control block).
  • Memory for the reference count must be dynamically allocated.
  • Increments and decrements of the reference count must be atomic.
  • Move constructing a shared_ptr from another shared_ptr sets the source shared_ptr to null, and that means that the old shared_ptr stops pointing to the resource a the moment the new shared_ptr starts. As a result no reference count manipulation is required.
  • shared_ptr also uses delete as its default resource-destruction mechanism, but it also supports custom deleters
  • shared_ptr supports copy assignment, copy construction, move assignment, move construction.
For example -

shared_ptr sp2 = std::move(sp1);
Here the state of sp1 is transferred to sp2, along with raw pointer, reference count, deleters etc (known as control block) and sp1 is set to null. Also note that in move construction, reference count is unchanged.

Like std::unique_ptr , shared_ptr also supports custom deleters. However the difference is, deleters is not a part of shared_ptr itself.

For instance, the below program proves that deleter function is not part of shared_ptr

#include<iostream>
#include<memory>

using namespace std;

int main()
{
    int x = 20; 
    float y = 10.9;
    string str = "Ravi Prakash Giri";
    auto deleteFun = [=] (int *xp)
    {   
        cout<<"X = "<<x<<endl;
        cout<<"Y = "<<y<<endl;
        cout<<"String - "<<str<<endl;
    };  

    std::unique_ptr<int, decltype(deleteFun)> uPtr(new int(20),deleteFun);
    
    std::shared_ptr<int> sPtr(new int(10),deleteFun);

    cout<<"Size of UniquePtr - "<<sizeof(uPtr)<<endl;
    cout<<"Size of SharedPtr - "<<sizeof(sPtr)<<endl;
    
}

Output - 
Size of UniquePtr - 24
Size of SharedPtr - 16

// sizeof(int) - 8

Here are some rules for creation of control block -
  • Creating shared_ptr using make_shared always creates a control block.
  • It is created when a shared_ptr is constructed from unique_ptr. ( unique_ptr is then set to null).
  • When shared_ptr is created using raw pointer.

Comments

  1. This comment has been removed by the author.

    ReplyDelete
  2. If we have a weak_ptr along with shared_ptr pointing to some memory location.
    There can be case when object will not be destroyed even if last shared_ptr stops pointing to that object.

    ReplyDelete

Post a Comment

Popular posts from this blog

C++ Guidelines for Multithreaded System

Signalling System #7(SS7) Protocol.