共享指针和弱引用指针失败的琐碎情况

32

我在使用shared_ptrweak_ptr以及enable_shared_from_this时遇到了问题。

当我搜索我看到的症状时,每个人都建议“当没有shared_ptr实例拥有您的对象时,您不能使用shared_from_this()

但这不是我的情况。

考虑以下代码:

#include <memory>
#include <cassert>

class MyClass : std::enable_shared_from_this<MyClass>
{
public:
    void this_fails()
    {
        // Doesn't even assert(), because it throws bad_weak_ptr
        assert(shared_from_this());
    }
    void this_fails_too()
    {
        std::weak_ptr<MyClass> weak = weak_from_this();
        std::shared_ptr<MyClass> strong = weak.lock();
        // This assert fails
        assert(strong.get());
    }
};

int main()
{
    std::shared_ptr<MyClass> obj = std::make_shared<MyClass>();

    obj->this_fails();
    obj->this_fails_too();
}

MyClass中的两种方法都会导致程序崩溃。我一定漏掉了什么显而易见的东西 - 是什么呢?

2个回答

42

你必须公开继承 std::enable_shared_from_this。私有继承没有帮助 - std::shared_ptr 无法访问基类并正确设置它。


8
那一定是我见过的最不符合直觉的行为之一。为什么它不会引起编译时错误呢?-- 解释在这里:https://dev59.com/PFkS5IYBdhLWcg3wYl3V - LubosD
9
没有简单的方法来产生编译错误。std::shared_ptr构造函数没有机制可以告诉你是否通过私有继承std::enable_shared_from_this发生了错误,还是仅通过某个公开继承std::enable_shared_from_this的类进行了私有继承。shared_from_this函数无法知道最派生类类型,因此也无法检测程序员的错误。 - Brian Bi
1
标准可以强制使用std::is_base_of检查基类,如果它是模糊的或不可访问的,则进行投诉。 - Deduplicator
1
@LubosD 令人困惑的是,一个类并不需要从 std::enable_shared_from_this 派生,但只有在这样做时才会发生某些事情。这非常不好,并且如果您分配了另一个使用成员而不是继承的类,则无法正常工作。最好拥有自己的 weak_ptr 并自行维护它。 - curiousguy
@Brian 无论如何你都会拥有。考虑到私有基础取决于管理被保存。 - Deduplicator
显示剩余2条评论

17

要使它起作用,你必须公开继承自std::enable_shared_from_this


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接