在C++ 11中使用shared_from_this()而不使用托管共享指针

Gus*_*avo 5 c++ pointers std shared-ptr c++11

假设我有一个类,它是enable_shared_from_this的子类.这个基类的文档说在调用shared_from_this之前应该有一个共享指针拥有这个类.使用new分配类并调用shared_from_this来管理对象是否安全?

sky*_*ack 6

正如其他用户已经提到的,调用shared_from_this不属于shared_ptrs 的实例将导致未定义的行为(通常是异常,但不能保证)。

那么,为什么还要多一个答案呢?

因为我自己也做过一次同样的问题并得到了几乎相同的答案,然后我开始努力解决此后立即出现的另一个问题 -我如何保证所有实例都由 a 管理shared_ptr

为了完整起见,我添加了另一个答案,其中包含有关这方面的一些细节。
这是一个以前没有提到过的简单解决方案。

确实如此简单的解决方案:私有构造函数工厂方法可变参数模板
它遵循一个片段,在一个最小的示例中将所有这些内容混合在一起:

#include<memory>
#include<utility>

class C: public std::enable_shared_from_this<C> {
    C() = default;
    C(const C &) = default;
    C(C &&) = default;
    C& operator=(const C &) = default;
    C& operator=(C &&c) = default;

public:
    template<typename... Args>
    static std::shared_ptr<C> create(Args&&... args) noexcept {
        return std::shared_ptr<C>{new C{std::forward<Args>(args)...}};
    }

    std::shared_ptr<C> ptr() noexcept {
        return shared_from_this();
    }
};

int main() {
    std::shared_ptr<C> c1 = C::create();
    std::shared_ptr<C> c2 = C::create(*c1);
    std::shared_ptr<C> c3 = c2->ptr();
    // these won't work anymore...
    // C c4{};
    // std::shared_ptr<C> c5 = std::make_shared<C>();
    // std::shared_ptr<C> c6{new C{}};
    // C c7{*c1};
    // ... and so on ...
}
Run Code Online (Sandbox Code Playgroud)

基本(微不足道?)的想法是禁止显式构造新实例,但通过使用此处称为 的工厂方法create
可变参数模板用于避免编写多个工厂方法,仅此而已。完美转发帮助我们以正确的方式做到这一点。

很简单,不是吗?
不管怎样,我花了一段时间才弄清楚这一点,所以我希望这能帮助未来遇到同样疑问的读者。


vit*_*aut 1

不,这不安全。shared_from_this您应该仅在对象由 a 管理shared_ptr而不是通过分配new(没有关联的)时调用shared_ptr。例如这段代码

struct Test: std::enable_shared_from_this<Test> {
  std::shared_ptr<Test> getptr() {
    return shared_from_this();
  }
};

Test *test = new Test;
std::shared_ptr<Test> test2 = test->getptr();
Run Code Online (Sandbox Code Playgroud)

会抛出std::bad_weak_ptr(至少在使用时libstdc++)。但这没关系:

std::shared_ptr<Test> test(new Test);
std::shared_ptr<Test> test2 = test->getptr();
Run Code Online (Sandbox Code Playgroud)