在C++中,内存管理一直是个棘手的问题。手动管理内存(new/delete)容易导致内存泄漏 和悬空指针。智能指针的出现,让内存管理变得安全又简单!
为什么需要智能指针?
cpp
// 手动管理内存的陷阱
void foo() {
int* p = new int(10);
// 如果这里发生异常或提前return,内存泄漏!
}
智能指针通过自动管理内存,在对象离开作用域时自动释放内存,彻底解决内存泄漏问题。
三种核心智能指针
unique_ptr - 独占所有权
-
特点 :一个指针只能由一个对象拥有,不能拷贝 ,可以移动
-
使用场景 :资源独占(如网络连接)
cpp#include <memory> std::unique_ptr<int> create_unique() { auto p = std::make_unique<int>(42); // 创建智能指针 return p; // 可以安全返回(移动语义) } int main() { auto p = create_unique(); std::cout << *p; // 输出 42 // 离开作用域时自动释放内存 }unique_ptr保证了资源的唯一所有权,避免了共享导致的释放冲突。
shared_ptr - 共享所有权
-
特点 :多个指针共享 同一资源,引用计数管理生命周期
-
使用场景 :需要多个对象共享同一资源(如缓存、单例)
cpp#include <memory> struct Resource { ~Resource() { std::cout << "资源释放\n"; } }; int main() { auto r1 = std::make_shared<Resource>(); { auto r2 = r1; // 引用计数+1 std::cout << "当前引用计数: " << r1.use_count() << "\n"; } // r2离开作用域,计数-1 std::cout << "当前引用计数: " << r1.use_count() << "\n"; // r1离开作用域时自动释放资源 }use_count()查看引用计数,当计数为0时自动释放。
weak_ptr - 弱引用
-
特点 :不增加引用计数 ,解决
shared_ptr的循环引用问题 -
使用场景 :观察者模式、缓存等需要避免循环引用的场景
cpp#include <memory> struct Node { std::shared_ptr<Node> next; std::weak_ptr<Node> prev; // 避免循环引用 }; int main() { auto a = std::make_shared<Node>(); auto b = std::make_shared<Node>(); a->next = b; b->prev = a; // 弱引用,不会增加计数 // 释放时不会因循环引用卡住 a.reset(); // 释放a,b的next被释放 }通过
lock()检查资源是否还有效:cppif (auto locked = weak_ptr.lock()) { // 资源有效,安全使用 }智能指针使用守则
表格
指针类型 不能拷贝 能移动 引用计数 适用场景 unique_ptr✅ ✅ ❌ 独占资源 shared_ptr❌ ✅ ✅ 共享资源 weak_ptr❌ ❌ ❌ 避免循环引用
为什么应该优先用智能指针?
- 安全:自动管理内存,避免内存泄漏
- 简洁:代码更短,逻辑更清晰
- 现代C++:是C++11标准的核心特性