楼层: 首页/ 软件技术/ 现代 C++/ RAII 与智能指针:C++ 最重要的范式
4

RAII 与智能指针:C++ 最重要的范式

RAII · unique_ptr · shared_ptr · weak_ptr

在 C 里你得 malloc 完记得 free,累不累?C++ 的答案是 RAII(资源获取即初始化):把资源绑在一个对象的生命周期上,对象出生时拿资源,对象销毁时自动还资源。哪怕中间抛异常、提前 return,析构函数也一定会跑。智能指针就是 RAII 的明星产品。

论为什么别再裸 new/delete

裸指针 T* p = new T; 有两个致命问题:① 忘了 delete,内存泄漏;② 中间抛异常或提前 return,delete 那行没走到。把它交给智能指针,这些烦心事自动消失。

三种智能指针

智能指针所有权模型
std::unique_ptr<T>独占:这块内存只有它一个主人。不能拷贝,只能 std::move 移走。首选,零开销。
std::shared_ptr<T>共享:引用计数,几个人一起用,最后一个走了才释放。有少量开销。
std::weak_ptr<T>旁观者:不增加引用计数,专门解决 shared_ptr 循环引用导致谁都不释放的问题。

现代写法:make_unique / make_shared

#include <memory> // 独占:离开作用域自动 delete,不用你管 auto p = std::make_unique<int>(42); std::cout << *p << "\n"; // 共享:两个指针指向同一个 int,引用计数=2 auto a = std::make_shared<int>(100); auto b = a; // 可以拷贝,引用计数变 2 // a 和 b 都离开作用域时,内存才真正释放 // unique_ptr 不能拷贝,只能移动: auto p1 = std::make_unique<int>(1); auto p2 = std::move(p1); // 所有权从 p1 转给 p2,p1 变空
循环引用死锁

两个对象互相持有 shared_ptr 指向对方,引用计数永远降不到 0,谁都不释放,内存泄漏。解法:把其中一方改成 weak_ptr——它"看着"对方但不占引用计数。口诀:能用 unique_ptr 就别用 shared_ptr;用 shared_ptr 时警惕循环,循环了就上 weak_ptr。