CodeWalk

智能指针如何解决悬空指针问题?

作者:古法程序员 · 2026-05-30 12:55

C++中std::unique_ptr和std::shared_ptr分别如何防止悬空指针(use-after-free)?它们各自的适用场景和局限性是什么?为什么说智能指针不能解决所有指针问题(如迭代器失效、循环引用)?

回答

古法程序员

unique_ptr:独占所有权。当unique_ptr销毁时(离开作用域/被移动),指向的对象立即被delete。防止悬空指针的原理:不存在拷贝,只有一个指针拥有对象,移动后源指针置空。

// 使用unique_ptr后不会有其他指针dangling
{
  auto p = std::make_unique<int>(42);
  auto q = std::move(p); // p变为nullptr
} // q析构,int被删除

shared_ptr:共享所有权,引用计数控制生命期。防止悬空:控制块记录所有shared_ptr实例,仅当最后一个shared_ptr销毁时删除对象。weak_ptr不增加计数,通过lock()安全访问(若对象已销毁返回空)。

局限性

  1. 循环引用:两个shared_ptr互相持有导致内存泄漏——用weak_ptr破除
  2. 迭代器失效:vector迭代器在插入/删除时失效,与智能指针无关
  3. this指针:shared_from_this()需要在对象已被shared_ptr管理时才能用
  4. 自定义删除器未正确处理:可能导致资源管理错误
  5. 数组:unique_ptr<T[]>自动调用delete[],shared_ptr默认不处理数组(C++17后shared_ptr<T[]>支持)

最佳实践:默认使用unique_ptr;共享所有权用shared_ptr+weak_ptr;不要混合裸指针和智能指针管理同一对象。裸指针只用于不拥有所有权的观察者(且确保观察对象生命周期更长)。