• enable_shared_from_this能让一个对象t(该对象被shared_ptr管理,假设名为pt)安全地生成其他额外的shared_ptr实例,它们pt共享对象t的所有权。
  • 如果一个类T继承enable_shared_from_this<T>,则会为该类提供成员函数:shared_from_this。只允许在被std::shared_ptr管理的对象上调用shared_from_this。否则调用会导致未定义行为(c++17前)or抛出std::bad_weak_ptr异常。
  • 关于enable_shared_from_this类的必要性和用法这里不再赘述。我们看在vs2017中它是如何实现的。

72.png

  • enable_shared_from_this是一个模板类,模板参数是你想要通过shared_from_this提供其他shared_ptr对象的类型。在这份实现中有一个成员类型_Esft_type,这个类型的用处在后面会说到。

73.png

  • 有一个成员变量,该变量类型为weak_ptr<_Ty>。

74.png

  • 我们使用的函数shared_from_this(),就是用这个成员变量构造对应的shared_ptr<_Ty>对象并返回的。

75.png

  • 这是shared_ptr接受一个weak_ptr作为参数的构造函数,如果构造失败,会抛出bad_weak_ptr异常(since c++17)。

76.png

  • 不过我们看到,在enable_shared_from_this的所有构造函数中,都没有对_Wptr进行赋值操作,那么这个成员变量是在哪里被赋值的呢?说到这里不知道大家还记不记得,我们在分析shared_ptr的源代码的时候,出现过这么一个函数:_Set_ptr_rep_and_enable_shared。
  • 其实看名字就可以看出来,这个函数做了两个操作:
    1.设置ptr和rep。
    2.enable_shared。我们来看下这个函数的内部实现:

77.png

78.png

  • 其中_Can_enable_shared<_Yty>根据_Yty类型是否具有_Esft_type成员类型而选择了不同的重载函数:

79.png

80.png

  • 如果不具有_Esft_type类型,则什么都不做,否则为_Ptr->_Wptr赋值。现在我们找到了enable_shared_from_this的成员变量_Wptr是在哪里被赋值了。只有继承了enable_shared_from_this类型的指针,其类型才会有_Esft_type成员类型,换句话说,这个成员类型就是用来区分shared_ptr的模板参数类型是否继承了enable_shared_from_this<T>这个类。
  • 总结:enable_shared_from_this的一种实现方法是,其内部有一个weak_ptr类型的成员变量_Wptr,当shared_ptr构造的时候,如果其模板类型继承了enable_shared_from_this,则对_Wptr进行初始化操作,这样将来调用shared_from_this函数的时候,就能够通过weak_ptr构造出对应的shared_ptr。

p__n
491 声望10 粉丝

科学告诉你什么是不可能的;工程则告诉你,付出一些代价,可以把它变成可行,这就是科学和工程不同的魅力。