【问题标题】:Recursive data-structures without the use of pointers不使用指针的递归数据结构
【发布时间】:2016-04-29 11:20:49
【问题描述】:

在我攻读计算机科学学士学位期间,我多次遇到递归数据结构的使用。在 C++ 中,我总是最终使用指针来使我的数据结构递归,就像我在 C 中所做的那样。

一个简化的例子如下:

struct Tree{
    int data;
    struct Tree *left, *right;
};

但是,使用指针往往是一项有风险的工作,并且需要花费大量时间调试和测试代码。对于这些问题,我想知道是否有任何其他有效的方法可以在 C++ 中定义递归数据结构。

在其他编程语言中,比如 Rust,我见过这样的事情:

struct Node {
    children: Vec<Node>,
    node_type: NodeType,
}

在 C++ 中定义这种递归结构是否有更安全和舒适的方法。一种可能是使用 std::Vector,但我不知道该方法的性能。

【问题讨论】:

  • @Robinson 这将立即结束应用程序 - 由于无限 Tree 对象创建:)
  • 在某些情况下,它实际上是使用指针的一个优势,例如在树状结构中。你怎么知道一棵树没有孩子?没有可用于结构的“空”值。
  • 至于为什么在 Rust 中允许,那是因为 Rust 不是 C++。两种不同的语言,无论它们的语法多么相似,都无法真正进行比较。至于 为什么 它在 Rust 中起作用可能是因为它使用 references (有点像指针)而不是实际的结构。
  • Rust 在这方面与 C++ 完全没有区别:你不能写 struct Tree { data: i32, left: Tree, right: Tree }。 Rust 的 Vec 内部包含方向,实际上它与 C++ 的 std::vector 基本相同。 (Rust 的结构和枚举是值,就像在 C++ 中一样,而不是指针/引用。)
  • @zakum,如果你对在 Rust 中使用 Box/Arc/Vec 感到满意,那么 C++ 中的等价物 (unique_ptr/shared_ptr/vector) 应该成为你正在寻找的东西。 (我意识到我在之前的评论中打错了:“direction”应该是“indirection”。)

标签: c++ pointers data-structures rust


【解决方案1】:

Rust 示例使用子向量 - 这也可以是空的。

在 C++ 中,成员变量可以是对象、指针或引用(为简单起见,省略)。

由于不能直接使用节点对象(这将无限循环)并且您不希望使用指针,您的选择是:

  • 也可以使用向量(尽管对于二叉树来说,这不是最方便的类型 - 但是您可以在代码中将其限制为始终为两个元素),

  • 使用地图(键可以是枚举 CHILD_LEFT、CHILD_RIGHT),

  • 重新考虑使用指针,或者更好的是:智能指针(这看起来是常规 unique_ptrs 的一个很好的用例)。

【讨论】:

  • 如果使用引用,代码会怎样? @Joachim Pileborg 说 Rust 就是这样做的。但是,使用unique_ptrs 的选项对我来说似乎也是最合理的。
  • @zakum 它需要一系列丑陋的黑客攻击(例如 Tree 的全局向量,Tree 的三个 ctors:空的,有一个孩子或两个孩子(因为你不能更改指向的引用)初始化后的变量),这只是创建......删除呢!)。我强烈建议使用 unique_ptrs。请注意,在 C++ 中,如果原始指针 从不 离开对象,那么使用它可能是安全的(只需编写适当的析构函数,并避免在 Tree 构造函数中分配)。
  • 感谢您的关注和时间。我接受你的回答是最好的。下次我一定会尝试使用uniqe_ptr
【解决方案2】:

使用指针而不是值的原因是因为您永远无法定义您的struct,因为它的大小将是无限递归的。

struct Tree{
    int data;
    struct Tree left, right;
};

忽略填充等,您可以将Tree 的大小近似为

sizeof(Tree) == sizeof(int) + sizeof(Tree) + sizeof(Tree)
//                     ^data         ^left          ^right

但是你可以看到,因为Tree 有两个Tree 成员,而这些成员本身有两个Tree 成员,而那些有两个Tree 成员......你可以看到这是怎么回事.

【讨论】:

  • 我知道这一点。然而,使用 C++ 风格的做事会让一些事情变得更容易,比如“垃圾收集”。这就是为什么我试图找到一种在 C++ 中定义递归数据结构的方法。如果我不够清楚,想想 std::Vector 是如何自己处理内存的。
猜你喜欢
  • 2015-06-16
  • 1970-01-01
  • 2016-03-13
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多