一 unique_ptr独占智能指针独占所有权同一时间只能有一个unique_ptr指向这块堆内存禁止拷贝只允许移动。不能拷贝unqiue_ptrint p2 p1编译报错可以移动unique_ptrint p2 move(p1)移动后p1变成空p2接管资源生命周期出作用域自动调用delete释放内存示例代码#include iostream #include memory using namespace std; int main() { // 创建unique_ptr管理堆上int unique_ptrint p1(new int(100)); cout *p1 endl; // unique_ptrint p2 p1; // ❌ 编译报错禁止拷贝独占 unique_ptrint p2 move(p1); // ✅ 移动所有权 cout *p2 endl; // p1 现在是空指针不能再使用*p1 return 0; } // 出作用域p2销毁自动释放堆内存不用手动delete要点1.底层析构的时候直接释放内存没有引用计数开销很小2.适用场景资源只需要一个管理者绝大多数场景优先用unique_ptr3.C14推荐写法auto p make_uniqueint(100)二 shared_ptr共享智能指针共享所有权维护引用计数每多一个shared_ptr指向同一块内存计数1对象析构计数-1引用计数减到0释放堆内存。引用计数单独存放在堆上不是存在对象内部拷贝允许拷贝时引用计数1移动原指针置空计数不变示例代码#include iostream #include memory using namespace std; int main() { shared_ptrint p1 make_sharedint(200); // 计数1 cout p1.use_count() endl; // use_count查看引用计数 shared_ptrint p2 p1; // ✅ 允许拷贝共享资源计数2 cout p2.use_count() endl; p1.reset(); // p1放弃管理计数1 cout p2.use_count() endl; return 0; } // 函数结束p2析构计数变成0释放内存致命问题循环引用内存泄漏两个对象ABA里面存shared_ptrBB里面存shared_ptr A持有BB持有A。两个对象析构的时候引用计数都减到1永远不为0内存永远不释放。struct B; struct A{ shared_ptrB b_ptr; ~A(){cout A析构endl;} }; struct B{ shared_ptrA a_ptr; ~B(){cout B析构endl;} }; int main() { shared_ptrA a make_sharedA(); shared_ptrB b make_sharedB(); a-b_ptr b; b-a_ptr a; // 出maina、b析构但是内部互相持有引用计数1 // A、B的析构函数**不会执行内存泄漏** return 0; }运行结果不会打印A析构B析构内存泄漏解决方案把其中一个shared_ptr改为weak_ptr三 weak_ptr弱引用不增加shared_ptr的引用计数不拥有资源只是“旁观”shared_ptr管理的对象weak_ptr不能直接解引用访问对象必须调用.lock()返回一个临时shared_ptrlock()底层是如何操作的拿到 weak_ptr 保存的控制块地址weak_ptr 内部只存控制块指针 对象指针不持有对象原子操作读取 use_count判断use_count 0如果 use_count 0对象已经被释放 → 直接返回空的shared_ptr如果 use_count 0尝试原子地把 use_count 1原子防止多线程并发释放构造一个新的 shared_ptr把对象指针、控制块指针交给这个新 shared_ptr 返回整个过程是原子的防止多线程下 “判断完还没加计数对象就被别的线程释放”可以用.expired()判断资源是否已经被释放专门解决shared_ptr循环引用问题修复上面循环引用代码把A内部的shared_ptrB改为weak_ptrB#include iostream #include memory using namespace std; struct B; struct A{ weak_ptrB b_ptr; // 弱指针不增加引用计数 ~A(){cout A析构endl;} }; struct B{ shared_ptrA a_ptr; ~B(){cout B析构endl;} }; int main() { shared_ptrA a make_sharedA(); shared_ptrB b make_sharedB(); a-b_ptr b; // weak_ptr赋值b的引用计数不会1 b-a_ptr a; return 0; } // 输出A析构 B析构内存正常释放当main函数结束1.b析构B内部a_ptr计数减1a的引用计数变成0-A对象释放2.A释放后weak_ptr自动失效没有指针再持有BB的引用计数变成0-B释放。使用weak_ptr访问对象示例shared_ptrint s make_sharedint(666); weak_ptrint w s; // cout *w; // ❌ weak_ptr不能直接解引用 shared_ptrint tmp w.lock(); // 拿到临时shared_ptr if(tmp ! nullptr) { cout *tmp endl; }