普通引用而不是 weak_ptr 来打破循环依赖
Plain reference instead of weak_ptr to break circular dependency
看看 std::weak_ptr
我在几个地方看到它可以用来打破由于使用 std::shared_ptr
循环依赖引起的内存泄漏。例如,请参见这两个已接受的答案:[1], [2].
采用最后引用的答案,建议的修复是:
#include <memory>
#include <iostream>
struct B;
struct A {
std::shared_ptr<B> b;
~A() { std::cout << "~A()\n"; }
};
struct B {
std::weak_ptr<A> a;
~B() { std::cout << "~B()\n"; }
};
void useAnB() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b = b;
b->a = a;
}
int main() {
useAnB();
std::cout << "Finished using A and B\n";
}
不过,这感觉有点矫枉过正,为什么不简单地使用引用呢?我知道在这个例子中 b->a
没有在构造函数中设置,所以引用不会真正削减它,所以我的问题是:
Is there a reason to use a std::weak_ptr
instead of a reference if
the point is to break circular dependency if we can set it in the
constructor?
注意: 我明白 std::weak_ptr
的用处是保存一个可以失效的引用。我的问题只涉及当要点专门打破循环依赖时的用处。
这里有一个稍微修改过的函数:
void useAnB() {
std::shared_ptr<B> oops;
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b = b;
b->a = a;
oops = b;
}
// use oops->a
}
如果 oops->a
是普通指针或引用,您怎么知道它不再引用有效对象?
您无法检查引用(或普通指针)是否引用现有对象,并且您不能 "reseat" 引用,例如在赋值中。
I understand the usefulness of std::weak_ptr
to hold a reference that can be invalidated. My question only concerns the usefulness when the point is exclusively to break circular dependency.
好吧,如果你有循环依赖(或者即使你没有)并且你想在其他地方存储对 'master' 对象的引用以便你可以访问它,你知道确定那个对象不会消失,而你可能想要这样做,那么是的,我会只使用一个引用,因为:
- 更便宜
- 它可能避免首先将主对象设为
shared_ptr
(而这些本身非常昂贵)
归根结底,就是设计您的对象以最好地执行您需要它们完成的任何工作。当然,std::weak_ptr
并不是每个少女祈祷的答案。
看看 std::weak_ptr
我在几个地方看到它可以用来打破由于使用 std::shared_ptr
循环依赖引起的内存泄漏。例如,请参见这两个已接受的答案:[1], [2].
采用最后引用的答案,建议的修复是:
#include <memory>
#include <iostream>
struct B;
struct A {
std::shared_ptr<B> b;
~A() { std::cout << "~A()\n"; }
};
struct B {
std::weak_ptr<A> a;
~B() { std::cout << "~B()\n"; }
};
void useAnB() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b = b;
b->a = a;
}
int main() {
useAnB();
std::cout << "Finished using A and B\n";
}
不过,这感觉有点矫枉过正,为什么不简单地使用引用呢?我知道在这个例子中 b->a
没有在构造函数中设置,所以引用不会真正削减它,所以我的问题是:
Is there a reason to use a
std::weak_ptr
instead of a reference if the point is to break circular dependency if we can set it in the constructor?
注意: 我明白 std::weak_ptr
的用处是保存一个可以失效的引用。我的问题只涉及当要点专门打破循环依赖时的用处。
这里有一个稍微修改过的函数:
void useAnB() {
std::shared_ptr<B> oops;
{
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b = b;
b->a = a;
oops = b;
}
// use oops->a
}
如果 oops->a
是普通指针或引用,您怎么知道它不再引用有效对象?
您无法检查引用(或普通指针)是否引用现有对象,并且您不能 "reseat" 引用,例如在赋值中。
I understand the usefulness of
std::weak_ptr
to hold a reference that can be invalidated. My question only concerns the usefulness when the point is exclusively to break circular dependency.
好吧,如果你有循环依赖(或者即使你没有)并且你想在其他地方存储对 'master' 对象的引用以便你可以访问它,你知道确定那个对象不会消失,而你可能想要这样做,那么是的,我会只使用一个引用,因为:
- 更便宜
- 它可能避免首先将主对象设为
shared_ptr
(而这些本身非常昂贵)
归根结底,就是设计您的对象以最好地执行您需要它们完成的任何工作。当然,std::weak_ptr
并不是每个少女祈祷的答案。