cpp
std::shared_ptr<int>
这是 C++11 引入的:
txt
智能指针(Smart Pointer)
完整理解:
txt
一个"自动管理 int 对象生命周期"的指针
它属于:
cpp
#include <memory>
中的内容。
一、先看传统指针的问题
传统写法:
cpp
int* p = new int(10);
这里:
new
→ 在堆上申请内存
返回:
txt
int*
也就是普通指针。
问题:容易内存泄漏
你必须手动:
cpp
delete p;
否则:
txt
内存泄漏
例如:
cpp
void test()
{
int* p = new int(10);
return; // 忘记delete
}
这块内存永远回收不了。
二、shared_ptr 的作用
于是 C++11 提供:
cpp
std::shared_ptr
用于:
txt
自动释放内存
三、这句代码是什么意思
cpp
std::shared_ptr<int> p;
拆开看:
1. shared_ptr
表示:
txt
共享所有权智能指针
意思:
txt
多个指针可以共同拥有同一个对象
内部使用:
txt
引用计数
管理生命周期。
2. <int>
模板参数。
表示:
txt
它管理的是 int 类型对象
类似:
cpp
std::vector<int>
里的 <int>。
3. 整体意思
cpp
std::shared_ptr<int> p;
等价理解:
txt
定义一个"管理 int 对象"的智能指针
四、最常见正确写法
通常这样创建:
cpp
auto p = std::make_shared<int>(10);
意思:
txt
在堆上创建 int(10)
并用 shared_ptr 管理
五、内部发生了什么
cpp
auto p = std::make_shared<int>(10);
大致等价于:
cpp
int* raw = new int(10);
但:
txt
shared_ptr 会自动 delete
你不需要:
cpp
delete
六、使用方式
读取值
cpp
std::cout << *p;
输出:
txt
10
因为:
cpp
*p
是解引用。
修改值
cpp
*p = 20;
七、shared(共享)是什么意思
这是 shared_ptr 最核心部分。
多个 shared_ptr 指向同一对象
cpp
auto p1 = std::make_shared<int>(100);
auto p2 = p1;
此时:
txt
p1 和 p2
共同拥有同一个 int
内存里:
txt
+--------+
p1 -->| int100 |
p2 -->| |
+--------+
八、引用计数
shared_ptr 内部有:
txt
引用计数(Reference Count)
创建时
cpp
auto p1 = std::make_shared<int>(100);
计数:
txt
1
拷贝后
cpp
auto p2 = p1;
计数:
txt
2
一个对象销毁
cpp
p2 离开作用域
计数:
txt
1
最后一个销毁
txt
计数=0
自动:
cpp
delete
释放内存。
九、例子
cpp
#include <iostream>
#include <memory>
int main()
{
auto p1 = std::make_shared<int>(10);
{
auto p2 = p1;
std::cout << p1.use_count() << std::endl;
}
std::cout << p1.use_count() << std::endl;
}
输出:
txt
2
1
十、为什么推荐 make_shared
推荐:
cpp
auto p = std::make_shared<int>(10);
不推荐:
cpp
std::shared_ptr<int> p(new int(10));
因为:
make_shared 优点
1. 性能更好
一次内存分配。
2. 更安全
避免异常导致泄漏。
3. 代码更简洁
十二、如何判断为空
cpp
if (b)
{
// 非空
}
else
{
// 空
}
十三、shared_ptr 内存结构
内部大概:
txt
shared_ptr
│
├── 指向对象
│
└── 引用计数控制块
例如:
txt
+----------------+
| control block |
| ref_count = 2 |
+----------------+
|
v
+-------+
| int10 |
+-------+
十四、shared_ptr 最大问题
循环引用
例如:
cpp
class A
{
shared_ptr<B> b;
};
class B
{
shared_ptr<A> a;
};
结果:
txt
A 引用 B
B 引用 A
引用计数永远不为 0。
导致:
txt
内存泄漏
解决方法
使用:
cpp
std::weak_ptr
打破循环引用。
十五、智能指针三兄弟
1. unique_ptr
独占所有权。
txt
一个对象只能有一个主人
不能复制。
性能最好。
2. shared_ptr
共享所有权。
可多个指针共享。
有引用计数开销。
3. weak_ptr
弱引用。
不增加引用计数。
用于:
- 观察对象
- 打破循环引用
十六、现代 C++ 推荐
现代 C++:
txt
尽量不要直接 new/delete
推荐:
cpp
make_unique
make_shared
RAII 自动管理资源。
十七、Qt 中的对应关系
Qt 里类似:
| STL | Qt |
|---|---|
| shared_ptr | QSharedPointer |
| weak_ptr | QWeakPointer |
| unique_ptr | QScopedPointer |
不过现代 Qt 项目:
很多人直接使用 STL 智能指针。