指针共享习语



我想不出在一般情况下这样做的方法。假设我有两个类,它们保持着指向彼此的指针:

class first {
    unique_ptr<second> p2;
public:
    first() : p2(this) {}
};
class second {
    first* p1;
public:
    second(first* arg) : p1(arg) {}
};

这一切都很好,但我真正想要的是使用shared_ptr作为second的一部分,因为second对象也可以独立于first创建。他们只会被传递一个指向构造中的first的指针,但他们不知道它是否已经消失。

我不能把second::p1变成shared_ptr,因为我不知道如何从first::first()传入this

有没有一个成语可以帮助我处理这个问题?

有可能需要注意的是,您只能在堆上创建实例。使用std::shared_from_this是一个不错的解决方案,但它只能在对象的std::shared_ptr存在时调用,这在构造函数完成之前是不可能的,即使在使用std::make_shared并抛出std::bad_weak_ptr异常时也是如此。

相反,我们确保创建此类实例的唯一方法是通过执行必要设置的静态函数。

#include <cassert>
#include <memory>
class second;
class first {
    struct Unconstructable {};
    std::unique_ptr<second> p2;
public:
    first(Unconstructable) : p2() {}
    static std::shared_ptr<first> create() { 
        Unconstructable u;
        auto f = std::make_shared<first>(u);
        f->p2 = std::make_unique<second>(f);
        return f;
    }
};
class second {
    std::shared_ptr<first> p1;
public:
    second(std::shared_ptr<first> arg) : p1(arg) {}
};
int main()
{
    auto f = first::create();
}

编辑:使用Unconstructable并不是真正必要的,但使用std::make_unique是必需的。如果我简单地将构造函数设为私有,那么即使我将其设为friend函数,std::make_unique也将无法编译,因为该实现使用内部助手函数。将私有struct作为构造函数参数是一种绕过此问题的方法,同时仍然可以防止在类本身之外进行构造。

从我的评论中复制OP表明这是他可以接受的答案。

不幸的是,没有安全的方法可以做到这一点——因为构造函数根本不知道对象是如何分配的。如果它根本不是动态分配的呢?

如另一条注释所示,enable_shared_from_this也不是一个解决方案——它只是允许从隐藏在类中的weak_ptr中获取shared_ptr。然而,只有在至少有一个shared_ptr已经创建并持有锁的情况下,这才是安全的——同样,这不是构造函数可以确保的。

相关内容

  • 没有找到相关文章

最新更新