【问题标题】:How std::enable_shared_from_this::shared_from_this worksstd::enable_shared_from_this::shared_from_this 如何工作
【发布时间】:2015-12-03 08:53:33
【问题描述】:

我只是无法理解std::enable_shared_from_this::shared_from_this 如何返回一个与现有指针共享所有权的共享指针。换句话说,你做this

std::shared_ptr<Foo> getFoo() { return shared_from_this(); }

因此,当您调用 getFoo 时,它究竟是如何获得另一个 shared_ptr 来共享所有权而不是创建一个拥有相同 this 的单独 shared_ptr

我需要理解这一点才能理解如何从某个对象创建 shared_ptr ,这些对象都增加相同的引用计数,而不是初始化单独的 shared_ptrs。

【问题讨论】:

  • 我看过描述通用实现的注释。在此之前,我也看过源代码。但是无法理解当第一个 shared_ptr 在类之外创建时,这个weak_ptr 是如何被初始化的。一个类无法知道我们已经将它的指针封装在一些shared_ptr 中。
  • 你也应该看看std::shared_ptr的来源。该注释明确指出,那里的代码确实检测到std::enable_shared_from_this 作为基类的存在。

标签: c++ c++11 shared-ptr


【解决方案1】:

enable_shared_from_this&lt;T&gt; 有一个 weak_ptr&lt;T&gt; 数据成员。 shared_ptr&lt;T&gt; 构造函数可以检测T 是否派生自enable_shared_from_this&lt;T&gt;。如果是,shared_ptr&lt;T&gt; 构造函数会将*this(即shared_ptr&lt;T&gt;)分配给enable_shared_from_this&lt;T&gt; 中的weak_ptr 数据成员。然后shared_from_this() 可以从weak_ptr&lt;T&gt; 创建一个shared_ptr&lt;T&gt;

可能的实现示例:

template<class D>
class enable_shared_from_this {
protected:
    constexpr enable_shared_from_this() { }
    enable_shared_from_this(enable_shared_from_this const&) { }
    enable_shared_from_this& operator=(enable_shared_from_this const&) {
        return *this;
    }

public:
    shared_ptr<T> shared_from_this() { return self_.lock(); }
    shared_ptr<T const> shared_from_this() const { return self_.lock(); }

private:
    weak_ptr<D> self_;

    friend shared_ptr<D>;
};

template<typename T>
shared_ptr<T>::shared_ptr(T* ptr) {
    // ...
    // Code that creates control block goes here.
    // ...

    // NOTE: This if check is pseudo-code. Won't compile. There's a few
    // issues not being taken in to account that would make this example
    // rather noisy.
    if (is_base_of<enable_shared_from_this<T>, T>::value) {
        enable_shared_from_this<T>& base = *ptr;
        base.self_ = *this;
    }
}

【讨论】:

  • shared_ptr 如何访问weak_ptrenable_shared_from_this 成员(我猜它是私有的)。
  • @Narek 可能是friend
  • 在 C++17 中,您可以使用编译时分支使if 检查(当前是伪代码)可编译为:if constexpr( ... ) { ... }
  • 为什么在拷贝构造函数&赋值中使用模板类enable_shared_from_this而不指定类型参数D有效?
  • @MatějKripner 因为它在类模板主体中。查看en.cppreference.com/w/cpp/language/dependent_name中的当前实例化
猜你喜欢
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 2017-02-17
  • 2019-05-22
  • 1970-01-01
  • 2020-06-28
相关资源
最近更新 更多