我在共享指针方面没有很多专业知识,但是是的,这似乎是对 weak_ptr 的非常恰当的用法。
在这种情况下,你只是很生气:
- 您希望将
InputConsumers 直接用作ModelControllers 的成员,因为它是一种微不足道的所有权关系。
- 您必须使用
shared_ptr 才能使其与weak_ptr 一起使用。
我认为这可以通过使用shared_ptr 作为成员对象的别名 来解决。根据C++.com:
此外,shared_ptr 对象可以通过指针共享所有权
同时指向另一个对象。这种能力是
称为别名(参见构造函数),通常用于指向
成员对象同时拥有它们所属的对象。
我自己从来没有做过,但这似乎适合你的情况:
- 拥有
InputConsumers 成员ModelControllers
- 每个人都有一个别名
shared_ptr
- 使用
weak_ptrs 在InputSender 中引用它们
编辑
这是一个完整的最小工作示例:
#include <iostream>
#include <memory>
using namespace std;
// A class to try our smart pointers on
struct Foo
{
Foo() { cout << "constructing Foo\n"; }
~Foo() { cout << "destructing Foo\n"; }
};
// A class that owns some Foo as members
struct Owner
{
// The actual members
Foo foo1;
Foo foo2;
// A fake shared pointer whose purpose is:
// 1) to be of type shared_ptr<>
// 2) to have the same lifetime as foo1 and foo2
shared_ptr<Owner> self;
// A fake deleter that actually deletes nothing
struct Deleter
{
void operator() (Owner *) { cout << "pretend to delete Owner\n"; }
};
Owner() : self(this, Deleter()) { cout << "constructing Owner\n"; }
~Owner() { cout << "destructing Owner\n"; }
};
// A class that holds a reference to a Foo
struct Observer
{
// A reference to a Foo, as a weak pointer
weak_ptr<Foo> foo_ptr;
Observer(const shared_ptr<Foo> & foo_ptr) : foo_ptr(foo_ptr)
{
cout << "constructing Observer\n";
}
~Observer() { cout << "destructing Observer\n"; }
void check()
{
if(foo_ptr.expired())
cout << "foo expired\n";
else
cout << "foo still exists\n";
}
};
int main()
{
// Create Owner, and hence foo1 and foo2
Owner * owner = new Owner;
// Create an observer, passing an alias of &(owner->foo1) to ctor
Observer observer(shared_ptr<Foo>(owner->self, &(owner->foo1)));
// Try to access owner->foo1 from observer
observer.check();
delete owner;
observer.check();
return 0;
}
打印出来:
constructing Foo
constructing Foo
constructing Owner
constructing Observer
foo still exists
destructing Owner
pretend to delete Owner
destructing Foo
destructing Foo
foo expired
destructing Observer
棘手的部分是能够创建一个weak_ptr 到owner->foo1(对于foo2 将是相同的)。为此,我们首先需要一个shared_ptr,它是owner->foo1 的别名。这只能通过以下方式完成:
shared_ptr<Foo> alias(other_shared_ptr, &(owner->foo1));
其中other_shared_ptr 是一个shared_ptr<T>,其生命周期至少与owner->foo1 的生命周期一样长。为了实现这一点,使用shared_ptr<T> 也是一个好主意,它也是owner 的成员,因为它可以确保生命周期相同。最后,我们需要一个有效的非空指针给它,因为我们不想在堆上创建任何东西,我们必须使用一个现有的对象。 this 是一个很好的候选者,因为我们知道它是有效的,并且只有在其成员被销毁后才会被销毁。因此我们的other_shared_ptr 是例如:
shared_ptr<Owner> self(this);
但是,这意味着当self 超出范围时,即在owner 的销毁期间,它将调用delete this。我们确实不希望发生这种删除,否则this 将被删除两次(这是未定义的行为,实际上是段错误)。因此,我们还为self 的构造函数提供了一个实际上不会删除任何内容的Deleter。
其余的代码应该用 cmets 不言自明。