我在共享指针方面没有很多专业知识,但是是的,这似乎非常适合使用weak_ptr
.
在这种情况下,您只会感到恼火:
- 您想
InputConsumer
直接使用 s 作为 s 的成员ModelController
,因为它是一种微不足道的所有权关系。
- 您被迫使用 a
shared_ptr
使其与 a 一起使用weak_ptr
。
我认为这是通过使用 ashared_ptr
作为成员对象的别名来解决的。根据C++.com:
此外,shared_ptr 对象可以共享指针的所有权,同时指向另一个对象。这种能力称为别名(参见构造函数),通常用于在拥有它们所属的对象时指向成员对象。
我自己从来没有做过,但这似乎适合你的情况:
- 有s
InputConsumer
的成员ModelController
shared_ptr
每个人都有一个别名
InputSender
在using weak_ptr
s中引用它们
编辑
这是一个完整的最小工作示例:
#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
to owner->foo1
(对于 将是相同的foo2
)。为此,我们首先需要一个shared_ptr
是 的别名owner->foo1
。这只能通过以下方式完成:
shared_ptr<Foo> alias(other_shared_ptr, &(owner->foo1));
其中other_shared_ptr
ashared_ptr<T>
的生命周期至少与 中的一个一样长owner->foo1
。为了实现这一点,使用shared_ptr<T>
也是成员的owner
a 是一个好主意,因为它可以确保生命周期是相同的。最后,我们需要一个有效的非空指针给它,因为我们不想在堆上创建任何东西,我们必须使用一个现有的对象。this
是一个很好的候选者,因为我们知道它是有效的,并且只有在其成员被销毁后才会被销毁。因此我们other_shared_ptr
的例如是:
shared_ptr<Owner> self(this);
但是,这意味着当self
超出范围时,即在 的销毁期间owner
,它将调用delete this
. 我们不希望发生这种删除,否则this
会被删除两次(这是未定义的行为,实际上是段错误)。因此,我们还向self
实际上不删除任何内容的 Deleter 的构造函数提供。
其余的代码应该是不言自明的注释。