我想不出在一般情况下这样做的方法。假设我有两个类,它们保持着指向彼此的指针:
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
已经创建并持有锁的情况下,这才是安全的——同样,这不是构造函数可以确保的。