Skip to content

Shared Ownership (std::shared_ptr) and Control Block

Shared Ownership (std::shared_ptr) and Control Block

Section titled “Shared Ownership (std::shared_ptr) and Control Block”

std::shared_ptr enables multiple owners to share a single heap-allocated object via a Reference-counted control block. While powerful, it carries significant overhead — atomic reference Counting, a separate heap allocation, and the risk of reference cycles — and should only be used When shared ownership is genuinely required.

std::shared_ptr<T> is a smart pointer that allows multiple owners to share a single heap-allocated Object. The object is destroyed when the last shared_ptr pointing to it is destroyed or reset [N4950 S20.11.3].

Every group of shared_ptr instances that refer to the same object share a control block Allocated on the heap:

Control Block (separate allocation from the object):
┌─────────────────────────────────────┐
│ strong_count (std::atomic<size_t>) │ Number of shared_ptr owners
│ weak_count (std::atomic<size_t>) │ Number of weak_ptr observers + 1 if strong > 0
│ deleter (function pointer) │ Called when strong_count reaches 0
│ allocator (function pointer) │ Called to deallocate the control block itself
└─────────────────────────────────────┘
std::shared_ptr<T> object layout:
┌──────────────────┐
│ T* ptr_ │ (pointer to the managed object)
│ ControlBlock* cb_│ (pointer to the control block)
└──────────────────┘
sizeof(std::shared_ptr<T>) == 16 (two pointers on x86_64)

The control block is allocated separately from the managed object, unless std::make_shared is used.

A control block is created at the following points:

  1. std::make_shared&lt;T&gt;(args...). Single allocation for object + control block
  2. std::shared_ptr&lt;T&gt;(new T(args...)). Separate allocations for object and control block
  3. std::allocate_shared&lt;T&gt;(alloc, args...). Uses custom allocator for both
  4. Constructing from a std::weak_ptr via weak_ptr::lock(). Reuses existing control block