【发布时间】:2008-12-17 22:47:35
【问题描述】:
我正在用 C++ 实现二叉树。传统上,我有一个指向左的指针和一个指向右的指针,但手动内存管理通常以泪水告终。这引出了我的问题...
数据结构是否适合使用 shared_ptr?
【问题讨论】:
标签: c++ data-structures shared-ptr tr1
我正在用 C++ 实现二叉树。传统上,我有一个指向左的指针和一个指向右的指针,但手动内存管理通常以泪水告终。这引出了我的问题...
数据结构是否适合使用 shared_ptr?
【问题讨论】:
标签: c++ data-structures shared-ptr tr1
我认为这取决于您将在哪里使用它们。我假设您正在考虑做的事情是这样的:
template <class T>
class BinaryTreeNode
{
//public interface ignored for this example
private:
shared_ptr<BinaryTreeNode<T> > left;
shared_ptr<BinaryTreeNode<T> > right;
T data;
}
如果您期望您的数据结构能够处理动态创建的节点,这将非常有意义。如果。但是,由于这不是正常的设计,我认为这是不合适的。
我的回答是,不,这不是使用 shared_ptr 的合适位置,因为 shared_ptr 的使用意味着对象实际上是共享的 - 但是,二叉树中的节点永远不会共享。然而,正如 Martin York 所指出的,为什么要重新发明轮子——已经有一个智能指针类型可以做我们正在尝试做的事情——auto_ptr。所以去吧:
template <class T>
class BinaryTreeNode
{
//public interface ignored for this example
private:
auto_ptr<BinaryTreeNode<T> > left;
auto_ptr<BinaryTreeNode<T> > right;
T data;
}
如果有人问为什么数据不是 shared_ptr,答案很简单 - 如果数据的副本对库的 client 有好处,他们会传入数据项和树节点制作副本。如果 client 认为复制是一个坏主意,那么 client 代码可以传入一个 shared_ptr,树节点可以安全地复制它。
【讨论】:
因为左右不共享 boost::shared_ptr 可能不是正确的智能指针。
这将是一个尝试 std::auto_ptr 的好地方
【讨论】:
是的,绝对的。
但是如果你有一个循环的数据结构要小心。如果您有两个对象,它们都具有彼此共享的 ptr,那么如果不手动清除共享 ptr,它们将永远不会被释放。在这种情况下可以使用弱 ptr。当然,这对于二叉树来说并不担心。
【讨论】:
在每个对象都有一个所有者的情况下,手动编写内存管理并不是那么困难,因此可以删除它在其析构函数中拥有的内容。
根据定义,一棵树由节点组成,每个节点都有一个父节点,因此显然是其单一所有者的候选者,这真是一个快乐的时刻。恭喜!
我认为在您的情况下开发这样的解决方案非常值得*,并且还尝试shared_ptr 方法,将差异完全隐藏在相同的界面后面,因此您可以在两者之间切换并比较性能差异一些现实的实验。这是了解shared_ptr 是否适合您的应用程序的唯一可靠方法。
(*对我们来说,如果你告诉我们进展如何。)
【讨论】:
永远不要将 shared_ptr 用于数据结构的节点。如果在任何时候共享所有权,它可能会导致节点的销毁被暂停或延迟。这可能会导致以错误的顺序调用析构函数。 在数据结构中,节点的构造函数包含与其他节点耦合的任何代码,而析构函数包含与其他节点分离的代码,这是一种很好的做法。以错误顺序调用的析构函数可能会破坏这种设计。
【讨论】:
shared_ptr 有一些额外的开销,特别是在空间要求方面,但如果您的元素是单独分配的,那么 shared_ptr 将是完美的。
【讨论】:
你甚至需要指针吗?看来你可以使用boost::optional<BinaryTreeNode<T> > left, right。
【讨论】: