# C++ 智能指针详解:从原理到实践
在现代 C++ 开发中,智能指针是内存管理的核心工具,它们帮助我们避免内存泄漏和悬空指针问题。
## 为什么需要智能指针?
传统的裸指针存在诸多问题:
```cpp
void problematic() {
int* ptr = new int(42);
// 如果这里抛出异常,内存泄漏!
doSomething();
delete ptr; // 可能永远执行不到
}
```
## 三种智能指针
### unique_ptr:独占所有权
`unique_ptr` 确保同一时间只有一个指针拥有资源:
```cpp
#include <memory>
auto ptr = std::make_unique<int>(42);
// std::unique_ptr<int> ptr2 = ptr; // 编译错误!
std::unique_ptr<int> ptr2 = std::move(ptr); // 转移所有权
```
**使用场景**:工厂函数返回值、类成员独占资源
### shared_ptr:共享所有权
多个指针可共享同一资源,引用计数归零时自动释放:
```cpp
auto sp1 = std::make_shared<std::string>("Hello");
auto sp2 = sp1; // 引用计数 = 2
std::cout << sp1.use_count() << std::endl; // 输出: 2
```
**注意**:避免循环引用!
### weak_ptr:打破循环引用
`weak_ptr` 是 `shared_ptr` 的观察者,不增加引用计数:
```cpp
class Node {
public:
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // 使用 weak_ptr 避免循环引用
};
```
## 性能对比
| 特性 | unique_ptr | shared_ptr | weak_ptr |
|------|------------|------------|----------|
| 开销 | 零开销 | 引用计数 | 引用计数 |
| 拷贝 | 不可拷贝 | 可拷贝 | 可拷贝 |
| 线程安全 | 否 | 计数安全 | 计数安全 |
1. **优先使用 make_unique/make_shared**
```cpp
// 推荐
auto ptr = std::make_unique<Widget>();
// 不推荐
std::unique_ptr<Widget> ptr(new Widget());
```
2. **函数参数传递**
```cpp
void process(Widget* w); // 不转移所有权
void consume(std::unique_ptr<Widget> w); // 转移所有权
```
## 总结
智能指针是现代 C++ 的基石。合理选择 `unique_ptr`、`shared_ptr` 和 `weak_ptr`,能让代码更安全、更易维护。