C++11 引入的智能指针彻底改变了 C++ 的内存管理方式。从手动 new/delete 到 RAII 自动管理,智能指针在保证性能的同时大幅减少了内存泄漏的风险。本文将深入分析三种智能指针的实现原理与适用场景。

unique_ptr:独占所有权

std::unique_ptr 是最轻量级的智能指针,它独占所管理对象的所有权,不支持拷贝,只支持移动语义。它的开销几乎为零——在默认删除器的情况下,大小与裸指针相同。

典型使用场景

// 工厂函数返回 unique_ptr
std::unique_ptr<Base> createObject(Type type) {
    switch (type) {
        case Type::A: return std::make_unique<DerivedA>();
        case Type::B: return std::make_unique<DerivedB>();
        default:      return nullptr;
    }
}

shared_ptr:共享所有权

std::shared_ptr 使用引用计数来管理对象的生命周期。当最后一个 shared_ptr 被销毁时,对象被自动释放。它比 unique_ptr 稍重——需要额外分配一个控制块来存储引用计数和删除器。

性能考量

weak_ptr:打破循环引用

std::weak_ptr 是 shared_ptr 的观察者,它不增加引用计数。最常见的用途是打破 shared_ptr 之间的循环引用——例如在双向链表或观察者模式中。

class Node {
    std::shared_ptr<Node> next;
    std::weak_ptr<Node>   prev;  // 使用 weak_ptr 避免循环引用
};

选择指南

  1. 默认使用 unique_ptr:开销最小,语义最清晰。只在确实需要共享所有权时才用 shared_ptr。
  2. 需要共享所有权时用 shared_ptr:确保使用 make_shared 创建。
  3. 需要观察但不拥有时用 weak_ptr:配合 lock() 方法安全访问。
  4. 不要用 shared_ptr 代替裸指针引用:如果一个函数只是使用对象而不参与所有权,传递裸引用或裸指针即可。
智能指针的正确使用让 C++ 的内存管理变得简单而安全——关键是理解所有权的语义。