C++学习系列(8):智能指针
1. 引言
在 C++ 中,手动管理内存(使用 new 和 delete)很容易导致 内存泄漏 或 悬空指针。
为了解决这个问题,C++ 提供了 智能指针(Smart Pointer) 来自动管理内存,避免手动 delete 的麻烦。
本篇博客,我们将学习:
- 智能指针的基本概念
- std::unique_ptr(独占所有权)
- std::shared_ptr(共享所有权)
- std::weak_ptr(弱引用,避免循环引用)
2. 智能指针概述
C++11 引入了智能指针,它们位于 <memory> 头文件中:
| 智能指针 | 特性 | 适用场景 |
|---|---|---|
std::unique_ptr | 独占所有权 | 资源只由一个指针管理 |
std::shared_ptr | 共享所有权 | 允许多个指针共享同一资源 |
std::weak_ptr | 弱引用,不影响计数 | 避免 shared_ptr 循环引用 |
3. std::unique_ptr(独占所有权)
特点
- 一个对象只能由一个
unique_ptr管理 - 无法进行复制,但可以移动
- 自动释放内存(无需手动
delete)
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "构造 MyClass\n"; }
~MyClass() { std::cout << "析构 MyClass\n"; }
void show() { std::cout << "Hello, unique_ptr!\n"; }
};
int main() {
std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
ptr->show();
// 不能复制,但可以转移所有权
std::unique_ptr<MyClass> ptr2 = std::move(ptr);
if (!ptr) std::cout << "ptr 已为空\n";
return 0;
}
📌 解析
std::make_unique<MyClass>()推荐创建unique_ptrunique_ptr不能复制,但可使用std::move进行 所有权转移- 退出作用域时,自动释放内存
4. std::shared_ptr(共享所有权)
特点
- 多个
shared_ptr可以共享同一对象 - 使用引用计数管理资源
- 当最后一个
shared_ptr释放时,资源被释放
#include <iostream>
#include <memory>
class MyClass {
public:
MyClass() { std::cout << "构造 MyClass\n"; }
~MyClass() { std::cout << "析构 MyClass\n"; }
void show() { std::cout << "Hello, shared_ptr!\n"; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::cout << "引用计数: " << ptr1.use_count() << std::endl;
std::shared_ptr<MyClass> ptr2 = ptr1; // 共享所有权
std::cout << "引用计数: " << ptr1.use_count() << std::endl;
return 0;
}
📌 解析
std::make_shared<T>()高效分配内存use_count()获取 引用计数- 引用计数归零时,自动释放内存
5. std::weak_ptr(防止循环引用)
为什么需要 weak_ptr?
如果 A 和 B 互相持有 shared_ptr,它们的引用计数永远不会归零,导致 内存泄漏(循环引用)。
解决方案
- 使用
std::weak_ptr弱引用,不会增加引用计数 weak_ptr需要转换为shared_ptr才能使用
#include <iostream>
#include <memory>
class B; // 先声明 B
class A {
public:
std::shared_ptr<B> ptrB;
~A() { std::cout << "A 被析构\n"; }
};
class B {
public:
std::weak_ptr<A> ptrA; // 使用 weak_ptr 解决循环引用
~B() { std::cout << "B 被析构\n"; }
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->ptrB = b;
b->ptrA = a; // 使用 weak_ptr 解决循环引用
return 0;
}
📌 解析
weak_ptr不会增加引用计数weak_ptr.lock()将weak_ptr转换回shared_ptr- 避免循环引用,防止内存泄漏
6. 智能指针对比总结
| 智能指针 | 主要特点 | 适用场景 |
|---|---|---|
unique_ptr | 独占所有权,不能复制 | 资源只需单一管理者 |
shared_ptr | 共享所有权,引用计数 | 资源被多个对象共享 |
weak_ptr | 不增加引用计数,防止循环引用 | 解决 shared_ptr 循环依赖问题 |
7. 什么时候使用智能指针?
✅ 适合使用智能指针的场景
- 需要 动态分配 内存,并自动管理资源
- 资源只属于一个对象(
unique_ptr) - 资源被多个对象共享(
shared_ptr) - 需要防止
shared_ptr循环引用(weak_ptr)
🚫 不适合使用智能指针的场景
- 栈对象(智能指针用于堆对象)
- 需要 显式控制对象生命周期 的场景
- 性能敏感的地方(智能指针带有额外的开销)
8. 总结
✅ std::unique_ptr:独占所有权,无法复制
✅ std::shared_ptr:共享所有权,引用计数
✅ std::weak_ptr:弱引用,避免 shared_ptr 循环引用
🎯 智能指针是 C++ 现代化开发的重要工具,推荐在合适的场景使用!
在下一篇 C++学习系列(9) 中,我们将深入学习 C++ 多线程编程,敬请期待!🚀
💡 如果你喜欢这篇文章,欢迎点赞、收藏,并关注本系列!
3万+

被折叠的 条评论
为什么被折叠?



