Middle
How is reference counting implemented in shared_ptr?
sobes.tech AI
Answer from AI
shared_ptr uses an internal control block that contains a strong reference count and a weak reference count.
Working mechanism:
- Creation: When the first
shared_ptrpointing to an object is created, a control block is created with both counters initialized to 1.#include <memory> int main() { auto ptr = std::make_shared<int>(10); // Control block created, strong_count = 1, weak_count = 1 (pointer in control block also counted) return 0; } - Copying
shared_ptr: When copying ashared_ptr, thestrong_countin the same control block is increased.#include <memory> int main() { auto ptr1 = std::make_shared<int>(10); // strong_count = 1 auto ptr2 = ptr1; // strong_count increases to 2 return 0; } - Assigning
shared_ptr: Assigning oneshared_ptrto another decreases thestrong_countof the left operand (if it pointed to an object) and increases thestrong_countof the right operand. - Creating
weak_ptr: When creating aweak_ptrfrom ashared_ptr, theweak_countin the same control block is increased. Thestrong_countremains unchanged.#include <memory> #include <weak_ptr> int main() { auto ptr = std::make_shared<int>(10); // strong_count = 1, weak_count = 1 std::weak_ptr<int> weak_ptr = ptr; // weak_count increases to 2 return 0; } - Exiting scope or resetting: When a
shared_ptris destroyed (e.g., when leaving scope or callingreset()), thestrong_countdecreases.#include <memory> int main() { { auto ptr = std::make_shared<int>(10); // strong_count = 1 } // strong_count decreases to 0 return 0; }#include <memory> int main() { auto ptr = std::make_shared<int>(10); // strong_count = 1 ptr.reset(); // strong_count decreases to 0 return 0; } - Releasing the object: When
strong_countbecomes 0, the object pointed to byshared_ptris deleted. - Releasing the control block: When both
strong_countandweak_countare 0, the control block is deleted. - Exiting scope or resetting
weak_ptr: When aweak_ptris destroyed, theweak_countdecreases.#include <memory> #include <weak_ptr> int main() { auto ptr = std::make_shared<int>(10); // strong_count = 1, weak_count = 1 { std::weak_ptr<int> weak_ptr = ptr; // weak_count = 2 } // weak_count decreases to 1 return 0; }
Reference counting is thread-safe due to atomic operations on counters within the control block.
Example of a control block structure (simplified):
struct ControlBlock {
std::atomic<long> strong_count{1};
std::atomic<long> weak_count{1}; // Initially 1, as the control block holds its pointer
// Additional info such as deleter, allocator
};