
智能指针用不好这些坑你可能都踩过std::shared_ptr循环引用导致内存泄漏std::unique_ptr在容器里编译不过std::weak_ptr什么时候该用——这些场景几乎每个C项目都会遇到。很多人只记住了“智能指针自动释放内存”但实际开发中问题往往出在所有权语义和生命周期管理上。shared_ptr最容易被误用的地方就是循环引用。比如两个对象互相持有对方的shared_ptr引用计数永远降不到0。解决方式是用weak_ptr打破环但不少人把weak_ptr当成“可空指针”来用每次访问前都要lock()代码变得臃肿。其实weak_ptr的正确用途是观察者模式或缓存场景而不是替代原始指针做参数传递。unique_ptr看似简单但在STL容器里容易踩坑。比如std::vectorstd::unique_ptrint调用push_back时必须用std::move否则编译报错。另外unique_ptr支持自定义删除器但删除器类型会被编码到指针类型中导致std::function作为删除器时内存占用膨胀。一个实用技巧是使用std::unique_ptrT, void(*)(T*)来避免类型擦除开销。性能方面shared_ptr的引用计数是原子操作多线程环境下开销明显。如果对象生命周期明确且不需要共享所有权优先用unique_ptr。对于需要共享但读多写少的场景可以结合shared_ptr和weak_ptr实现线程安全的缓存避免引用计数频繁增减。实际项目中滥用shared_ptr导致的性能问题比内存泄漏更常见尤其是高频调用的回调或事件系统里。版本兼容也得留意。C11的make_shared在C14/17里行为一致但std::make_unique直到C14才正式引入。如果项目还在用C11要么自己实现一个简易版本要么直接用new配合unique_ptr构造但这样会多一次内存分配。另外shared_ptr的别名构造函数aliasing constructor在C17里才稳定早期编译器可能有bug。调试时shared_ptr的引用计数变化很难追踪。可以用use_count()打日志但注意在多线程环境下这个值只是快照。更好的办法是使用AddressSanitizer或Valgrind检测泄漏或者重写删除器来打印释放信息。对于unique_ptr移动后原指针为null如果后续误用会导致空指针崩溃建议在移动后立即将原变量置空或限制作用域。总的来说智能指针不是银弹。理解所有权语义、避免循环引用、注意性能开销、适配编译器版本才能把C智能指针用好。实际开发中unique_ptr应该作为默认选择shared_ptr只在确实需要共享所有权时使用weak_ptr用来解决观察和缓存问题别让它承担原始指针的角色。