shared_from_this() 是一个成员函数,用于在类中获取指向当前对象的 std::shared_ptr。它通常在类中被调用,用于获取一个指向自身的共享指针。

  1. 强制要求对象必须通过 std::shared_ptr 进行持有:shared_from_this() 只能在已经通过 std::shared_ptr 进行管理的对象上被调用。如果尝试在未被 std::shared_ptr 管理的对象上调用该函数,将会抛出 std::bad_weak_ptr 异常。
  2. 获取同一个对象的共享指针:通过调用 shared_from_this(),可以获取一个指向同一对象的新的 std::shared_ptr,无需重新创建和拷贝 std::shared_ptr 对象本身。
  3. 避免循环引用导致内存泄漏:通常,在对象间存在循环引用时,由于引用计数无法降为零,导致对象无法正确析构从而产生内存泄漏。使用 shared_from_this() 可以在类内部获取一个指向自身的 std::shared_ptr,从而让循环引用的对象在适当的时候被析构,避免内存泄漏。

需要注意的是,为了使用 shared_from_this(),类必须从 std::enable_shared_from_this 派生,并且在创建对象时必须使用 std::shared_ptr 进行管理,而不是使用裸指针。否则,尝试调用 shared_from_this() 将导致未定义行为。

下面是demo:

当一个类public继承enable_shared_from_this时,会获得一个共有方法shared_from_this:

class T : public enable_shared_from_this<T> {

};

shared_ptr<T>  shared_from_this();

这个东西的引入是为了解决下面的这个问题:某个类的对象内存的生命周期由智能指针来管理,此时要在一个类的成员函数中,对外部返回shared_ptr构造的this指针会有问题。注意这里返回原生的this指针是可以的。核心的问题,就是:

  • 1. 如果采用返回拷贝,那么临时变量会把this析构掉

  • 2. 如果采用返回引用,那么obj对象本身必须持有一个管理他的shared_ptr,这样会导致obj永远不会被释放

    可用的解决方案有以下两种

    void getSharedFromParam(shared_ptr<obj>& p) {
    
      p.reset(this);    // 通过函数参数来实现规避掉拷贝语义,但是这样太过于丑陋
    
    }
    
    shared_ptr<obj> getSharedFromThis() {
    
      return shared_from_this();  // 这是C++11推荐的方法,可以实现安全的返回一个shared_ptr<this>,返回到外面的shared_ptr的拷贝的use_count是1,不用担心this被意外delete和引用计数异常的问题。
    
    }
    

注意:当你想使用getSharedFromThis时,必须以智能指针构造,而非以raw指针形式。否则会报std::bad_weak_ptr的错

int main() {

  auto p =std::make_shared<obj>();

  // auto p = new obj();

  p->getSharedFromThis()->doSomething();

}

enable_shared_from_this类中使用了一个私有weak_ptr来保存地址,在shared_from_this()通过把这个weak_ptr转换为引用计数为1的shared_ptr返回,避免了临时shared_ptr析构导致this被delete。