使用 boost::shared_ptr 时有哪些潜在危险?
在使用 boost::shared_ptr
?换句话说,当我使用 <代码>boost::shared_ptr?
推荐答案
循环引用:一个 shared_ptr<>
指向具有 shared_ptr<>
到原始对象.当然,您可以使用 weak_ptr<>
来打破这个循环.
Cyclic references: a shared_ptr<>
to something that has a shared_ptr<>
to the original object. You can use weak_ptr<>
to break this cycle, of course.
我添加以下内容作为我在评论中谈论的内容的示例.
I add the following as an example of what I am talking about in the comments.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
if (parent_) parent_->frob();
}
private :
void do_frob();
shared_ptr<node> parent_;
vector< shared_ptr<node> > children_;
};
在这个例子中,你有一个节点树,每个节点都有一个指向其父节点的指针.frob() 成员函数,无论出于何种原因,都会在树中向上波动.(这并不完全是古怪的;一些 GUI 框架就是这样工作的).
In this example, you have a tree of nodes, each of which holds a pointer to its parent. The frob() member function, for whatever reason, ripples upwards through the tree. (This is not entirely outlandish; some GUI frameworks work this way).
问题是,如果你失去对最顶层节点的引用,那么最顶层节点仍然拥有对其子节点的强引用,并且其所有子节点也对其父节点保持强引用.这意味着存在循环引用,使所有实例无法自行清理,而无法从代码中实际到达树,从而导致内存泄漏.
The problem is that, if you lose reference to the topmost node, then the topmost node still holds strong references to its children, and all its children also hold a strong reference to their parents. This means that there are circular references keeping all the instances from cleaning themselves up, while there is no way of actually reaching the tree from the code, this memory leaks.
class node : public enable_shared_from_this<node> {
public :
void set_parent(shared_ptr<node> parent) { parent_ = parent; }
void add_child(shared_ptr<node> child) {
children_.push_back(child);
child->set_parent(shared_from_this());
}
void frob() {
do_frob();
shared_ptr<node> parent = parent_.lock(); // Note: parent_.lock()
if (parent) parent->frob();
}
private :
void do_frob();
weak_ptr<node> parent_; // Note: now a weak_ptr<>
vector< shared_ptr<node> > children_;
};
这里,父节点已经被弱指针替换了.它在它所引用的节点的生命周期中不再有发言权.因此,如果最上面的节点像前面的例子一样超出范围,那么虽然它持有对其子节点的强引用,但它的子节点不持有对其父节点的强引用.因此没有对该对象的强引用,它会自行清理.反过来,这会导致孩子们失去他们的一个强引用,这会导致他们清理,依此类推.简而言之,这不会泄漏.只需从战略上将 shared_ptr<> 替换为 weak_ptr<>.
Here, the parent node has been replaced by a weak pointer. It no longer has a say in the lifetime of the node to which it refers. Thus, if the topmost node goes out of scope as in the previous example, then while it holds strong references to its children, its children don't hold strong references to their parents. Thus there are no strong references to the object, and it cleans itself up. In turn, this causes the children to lose their one strong reference, which causes them to clean up, and so on. In short, this wont leak. And just by strategically replacing a shared_ptr<> with a weak_ptr<>.
注意:以上内容同样适用于 std::shared_ptr<> 和 std::weak_ptr<>,就像 boost::shared_ptr<> 和 boost::weak_ptr<> 一样.
Note: The above applies equally to std::shared_ptr<> and std::weak_ptr<> as it does to boost::shared_ptr<> and boost::weak_ptr<>.
相关文章