概述
- 关于
shared_ptr
智能指针对象管理内存的情况- 不同的
shared_ptr
对象管理不同的内存 - 多个
shared_ptr
对象管理同一块内存
- 不同的
- 对于管理不同的内存
- 因为每个
shared_ptr
对象都有各自的控制块,因而引用计数独立,所有不存在问题
- 因为每个
- 对于管理同一块内存
- 因为每个
shared_ptr
对象都有各自的控制块,因为引用计数独立,但是它们之间不会同步这个引用计数的改动,所有会存在问题
- 因为每个
示例
1 2 3 4 5 6 7 8 |
class Object { public: void foo() { // 错误:用 this 直接构造 shared_ptr std::shared_ptr<Object> p1(this); std::shared_ptr<Object> p2(this); } }; |
问题1
- 其中一个
shared_ptr
对象的引用计数为0
时,它会释放管理的内存 - 于是,多个
shared_ptr
对象指向的同一块内存,此时已经被释放了 - 但是,由于控制块不同,引用计数不同步,其他的
shared_ptr
对象的引用计数此时可能还不为0
- 于是,引用计数不为
0
,该shared_ptr
对象认为所管理的内存还没被释放,它访问了该内存 - 导致访问已释放内存(野指针)
问题2
- 其中一个
shared_ptr
对象的引用计数为0
时,它会释放管理的内存 - 于是,多个
shared_ptr
对象指向的同一块内存,此时已经被释放了 - 但是,由于控制块不同,引用计数不同步,其他的
shared_ptr
对象的引用计数此时可能也刚好为0
- 于是,引用计数为
0
,那就要释放管理的内存,所以该shared_ptr
对象对已经释放的内存再次释放 - 导致双重释放(程序崩溃)
解决
- 使用
std::enable_shared_from_this
std::enable_shared_from_this
- 当你的类继承
std::enable_shared_from_this
后:- 所有通过
shared_from_this()
生成的shared_ptr
共享同一个控制块:
shared_from_this()
会返回一个与已有shared_ptr
共享控制块的智能指针
即使多次调用shared_from_this()
,所有生成的shared_ptr
都会引用同一个控制块 - 引用计数同步:
所有shared_ptr
共享同一个引用计数,确保对象只在所有引用计数归零时释放一次
- 所有通过
1 2 3 |
class mgr : public test::del, public std::enable_shared_from_this<mgr> { // ... }; |
- 注意
- 在调用
shared_from_this()
之前,对象必须已经由一个shared_ptr
管理(例如通过工厂方法创建): - 就是说,类继承了
enable_shared_from_this
之后,要先创建一个shared_ptr
对象,确保它被shared_ptr
管理,然后之后的shared_ptr
再通过shared_from_this
来创建
- 在调用
1 2 3 4 |
// 工厂方法确保对象由 shared_ptr 管理 static std::shared_ptr<mgr> create() { return std::shared_ptr<mgr>(new mgr()); } |
- 示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include <memory> #include <iostream> class test { public: class del { public: virtual void tes() = 0; virtual void hel() = 0; virtual ~del() = default; }; explicit test(std::shared_ptr<del> ddel) : de_(ddel) {} void qu() { if (auto sh = de_.lock()) { sh->tes(); } } private: std::weak_ptr<del> de_; }; class mgr : public test::del, public std::enable_shared_from_this<mgr> { public: // 工厂方法确保对象由 shared_ptr 管理 static std::shared_ptr<mgr> create() { return std::shared_ptr<mgr>(new mgr()); } void start() { // 正确:通过 shared_from_this() 获取 shared_ptr test t(shared_from_this()); t.qu(); } private: mgr() = default; // 构造函数私有化 void tes() override { std::cout << "tes" << std::endl; } void hel() override {} }; int main() { auto m = mgr::create(); // 通过工厂方法创建对象 m->start(); return 0; } |
声明:本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ C++编程规范101规则、准则与最佳实践 一01/05
- ♥ C++标准库 _string04/16
- ♥ Soui三05/19
- ♥ 深度探索C++对象模型一02/09
- ♥ Json库RapidJson使用01/11
- ♥ C++17_第二篇12/22