┌─────────────────┬──────────────────────┬──────────────────────┬─────────────────────────┐
│ Smart Pointer │ Ownership Model │ Overhead │ Copy / Move Ability │
├─────────────────┼──────────────────────┼──────────────────────┼─────────────────────────┤
│ std::unique_ptr │ Exclusive Single │ 0 bytes (Same as raw)│ Move-Only (No copy) │
│ std::shared_ptr │ Shared Ref-Counted │ 16-24 bytes (Control)│ Copyable & Moveable │
│ std::weak_ptr │ Non-owning Observer │ Control Block Pointer│ Breaks circular cycles │
└─────────────────┴──────────────────────┴──────────────────────┴─────────────────────────┘Smart Pointers in C++: unique_ptr, shared_ptr, and weak_ptr
Direct Answer & Core Concept
Detailed Explanation & Mechanics
1. Smart Pointer Comparison:
2. Circular Reference Prevention:
Two shared_ptr objects referencing each other create a reference count that never drops to 0. Replacing one side with std::weak_ptr resolves the leak.
Runnable Code Example: Smart Pointers in C++
C++20 / C++23#include <iostream>
#include <memory>
#include <string>
class Resource {
public:
std::string name;
explicit Resource(std::string n) : name(std::move(n)) {
std::cout << "[Constructed] Resource: " << name << "\n";
}
~Resource() {
std::cout << "[Destroyed] Resource: " << name << "\n";
}
};
int main() {
// 1. std::unique_ptr (Exclusive Ownership)
std::cout << "--- unique_ptr Demo ---\n";
{
auto uPtr = std::make_unique<Resource>("Unique-01");
// auto uCopy = uPtr; // COMPILE ERROR: Cannot copy unique_ptr!
auto uMoved = std::move(uPtr); // Ownership transferred
} // Destroyed here
// 2. std::shared_ptr and std::weak_ptr
std::cout << "\n--- shared_ptr & weak_ptr Demo ---\n";
std::weak_ptr<Resource> observer;
{
auto sPtr1 = std::make_shared<Resource>("Shared-02");
observer = sPtr1;
std::cout << "Shared use count: " << sPtr1.use_count() << "\n";
{
auto sPtr2 = sPtr1; // Ref count = 2
std::cout << "Shared use count in inner scope: " << sPtr1.use_count() << "\n";
} // sPtr2 leaves scope, Ref count = 1
std::cout << "Shared use count after inner scope: " << sPtr1.use_count() << "\n";
} // sPtr1 leaves scope, Ref count = 0 -> Resource destroyed
std::cout << "Is observed object expired? " << (observer.expired() ? "YES" : "NO") << "\n";
return 0;
}Common C++ Technical Interview Questions & Answers
Interview PrepQ: Why should you use `std::make_unique` and `std::make_shared` instead of `new`?
Q: How does `std::weak_ptr` access its underlying object?
Key Takeaways, Modern Best Practices & Idioms
C++ Best Practices & Production Rules
std::unique_ptr by default; upgrade to std::shared_ptr only when multiple entities genuinely share ownership.• Always use
std::make_unique and std::make_shared instead of raw new.• Use
std::weak_ptr for observer patterns and tree parent/sibling pointers to prevent circular dependency memory leaks.