服务端阅读 06月1日 10:30
C++ 智能指针怎么选?unique_ptr/shared_ptr/weak_ptr 使用场景对比
C++ 提供三种智能指针,均位于 <memory> 头文件。unique_ptr 独占所有权,不可拷贝只能移动,开销接近裸指针,是默认首选。shared_ptr 共享所有权,内部维护引用计数,最后一个持有者销毁时释放资源,拷贝和赋值增加计数。weak_ptr 是 shared_ptr 的观察者,不增加引用计数,通过 lock() 获取临时 shared_ptr 访问对象,用于打破循环引用。make_unique 和 make_shared 在单次分配中同时构造对象和控制块(后者),比单独 new 更高效且异常安全。自定义删除器允许在析构时执行特定操作,如 unique_ptr<FILE, decltype(&fclose)> 或传入 lambda 关闭文件句柄、释放 C 库资源。选择原则:独占用 unique_ptr,共享用 shared_ptr,观察用 weak_ptr,尽量避免混用裸指针持有所有权。追问makeshared 比 sharedptr(new T) 好在哪?make_shared 一次分配同时容纳对象和控制块,减少一次内存分配,且提高缓存局部性。但会延迟对象内存释放:即使引用计数归零,若 weak_ptr 仍存在,对象内存不会回收,直到 weak_ptr 也销毁。uniqueptr 的自定义删除器为什么比 sharedptr 更重?unique_ptr 的删除器类型是模板参数的一部分,影响指针类型本身,可能导致不同的 unique_ptr 类型不兼容。shared_ptr 的删除器类型在运行时擦除,不影响 shared_ptr<T> 类型,使用更灵活。智能指针线程安全吗?控制块(引用计数)的修改是原子的,shared_ptr 拷贝/析构线程安全。但访问所指对象不是线程安全的,多线程读写对象本身仍需加锁。unique_ptr 整体非线程安全,移动操作需外部同步。什么时候仍需要裸指针?不涉及所有权时用裸指针或引用作为观察者,如函数参数传递、遍历容器元素。裸指针不管理生命周期,只是访问地址,比 weak_ptr 更轻量。