看看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
并未在构造函数中设置,因此引用不会真正切掉它,所以我的问题是:
是否有理由使用
std::weak_ptr
代替引用,如果 关键是要打破循环依赖关系,如果我们可以在 构造函数?
注意::我了解std::weak_ptr
用来保存可以无效的引用的有用性。我的问题仅涉及仅在打破循环依赖时的用处。
答案 0 :(得分:1)
这是一个稍作修改的功能:
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
是一个普通的指针或引用,您怎么知道它不再指向有效的对象呢?
答案 1 :(得分:1)
您不能检查引用(或普通指针)是否引用了现有对象,也不能“重置”引用,例如在分配中。
答案 2 :(得分:0)
我了解
std::weak_ptr
持有可被无效的引用的有用性。我的问题仅涉及仅在打破循环依赖时的用处。
好吧,如果您具有循环依赖关系(或者甚至没有),并且希望将对“主”对象的引用存储在其他位置,以便可以访问它,并且可以肯定知道该对象不会消失,而您可能想要这样做,那么是的,我只使用引用,因为:
shared_ptr
(而且它们本身非常昂贵)最后,归结为设计对象以最佳地执行您需要它们执行的任何工作。当然,std::weak_ptr
并不是每个少女祈祷的答案。