你真的理解 shared_ptr 吗
文章目录
C++ 的 shared_ptr
是什么呢?你真的理解吗?让我们试着回答以下问题。
- 下面的几行代码是否正确,是否存在差异?
1
2
3std::shared_ptr<int> p1;
std::shared_ptr<int> p2(new int(0));
std::shared_ptr<int> p3 = std::make_shared<int>(0); void func(Class *A);
的参数可以是std::shared_ptr<A>
吗?shared_ptr<T>
是线程安全的吗?- 类成员函数如何返回指向自身的
shared_ptr
? - 如何自定义
shared_ptr
的释放行为?
问题解答
1. shared_ptr(new T) 与 make_shared()
在 C++ 中,shared_ptr
内部有一个指向动态分配对象的指针和一个指向控制块的指针。指向同一对象的共享指针共享这两个块。
1 | std::shared_ptr<int> p1; // 空对象,数据指针指向空,分配控制块内存,并计数 0 |
make_shared
只分配一次内存,效率更高,且能够有效避免内存碎片的产生。
2. 获取裸指针
std::shared_ptr<T>
构造函数中传入了一个对象指针。它同时提供了一个 get()
方法用来返回裸指针,但是在使用裸指针时要注意其生命周期。
3. shared_ptr 是线程安全的吗?
shared_ptr
的引用计数是原子操作,因此是线程安全的。但是 shared_ptr
指向的对象以及 shared_ptr
自身并不是线程安全的。在多线程中修改 shared_ptr
指向的数据或修改 shared_ptr
自身的指向可能对其他线程的 shared_ptr
造成破坏。
4. enable_shared_from_this
考虑下面的代码会有什么问题。
1 |
|
运行这段代码会发现 A
会被析构两次。因为 std::shared_ptr<A>(this)
会增加一次引用计数,而返回的 shared_ptr
和之前的 shared_ptr
是没有关联的,所以会各自析构一次。下面的代码有同样的问题。
1 | void test(){ |
enable_shared_from_this
就是为了解决通过对象获取自身的智能指针的问题。
1 |
|
enable_shared_from_this
内部也是通过 weak_ptr
的原理来实现的。
5. 自定义 shared_ptr 删除器
1 |
|