<C++>shared_ptrs利用std::enable_shared_from_this()实现安全管理this指针

来源:互联网 发布:杭州淘宝客服真实工资 编辑:程序博客网 时间:2024/05/16 09:37

智能指针大法好,但是坑儿免不了,不要哭来不要闹,C艹面前谁敢diao

利用RAII来管理资源自然是高效,但是对于一些比较特殊的类型,还是会有不得不注意的地方,没错说的就是std::shared_ptrthis指针的搭配。
shared_ptr的内部实现包括一个指向目标对象的raw pointer和一个包含reference count等其他维护sp状态的数据结构,称之为控制块(control block),形如下图:

control block

一个被shared_ptr包裹的对象原则上只能有一块control block,这样子对象的生命周期才能被正确管理,control block的建立遵循以下三条原则:

  • shared_ptr是从一个raw pointer构造而来时
  • shared_ptr从一个unique_ptr构造而来时
  • shared_ptr通过make_shared函数构造而来时

以上可以看出,连续的从同一个raw pointer构造智能指针是一种非常不好的编程习惯:

auto pt=new Object;std::shared_ptr spt(pt);std::shared_ptr spt2(pt);

以上,应该绝对避免,或者就像下面这样写:

auto pt=new Object;std::shared_ptr spt(pt);std::shared_ptr spt2{spt};

接下来进入正题!

当在类内想通过对this指针进行包裹来达到自动管理资源的目的时,很容易写出这样的代码:

class Object;std::vector<std::shared_ptr<Object>> spts_obj;//...class Object{public:    void process();}//...void Object::process(){   spts_obj.emplace_back(this);}

想法没毛病,只是想通过多个shared_ptr管理同一个对象罢了,但是!! 当通过this指针构造shared_ptr时,是会重新构造一个control block时的,不同的control block管理着同一个对象,指甲盖想想都知道大错特错了。
这时候就该std::enable_shared_from_this()出场了。cppreference
std::enable_shared_from_this()是一个模板类,使得多个通过this构造的智能指针共享同一块control block成为可能。
它有两个重要的成员函数:

  • shared_from_this:返回一个共享同一个this指针的shared_ptr对象
  • weak_from_this:返回一个共享同一个this指针的weak_ptr对象

以及一个成员对象:

  • weak_this:一个追踪control block状态的std::weak_ptr对象

将之前的代码改写一下,就可以做到多个shared_ptr安全管理同一个this指针了。

class Object;std::vector<std::shared_ptr<Object>> spts_obj;//...class Object: public std::enable_shared_from_this<Object>{public:    void process();}//...void Object::process(){   spts_obj.emplace_back(shared_from_this());}

注意一定是public继承!!!
虽然这样的继承写法看起来有点鬼畜,但是成功达到了目的不是么。