【问题标题】:Array as a struct field数组作为结构字段
【发布时间】:2015-05-15 15:08:55
【问题描述】:

我想在 Rust 中创建一个非二叉树结构。这是一个尝试

struct TreeNode<T> {
    tag : T,
    father : Weak<TreeNode<T>>,
    childrenlists : [Rc<TreeNode<T>>]
}

很遗憾,这无法编译。

main.rs:4:1: 8:2 error: the trait `core::marker::Sized` is not implemented for the type `[alloc::rc::Rc<TreeNode<T>>]` [E0277]
main.rs:4 struct TreeNode<T> {
main.rs:5     tag : T,
main.rs:6     father : Weak<TreeNode<T>>,
main.rs:7     childrenlist : [Rc<TreeNode<T>>]
main.rs:8 }
main.rs:4:1: 8:2 note: `[alloc::rc::Rc<TreeNode<T>>]` does not have a constant size known at compile-time
main.rs:4 struct TreeNode<T> {
main.rs:5     tag : T,
main.rs:6     father : Weak<TreeNode<T>>,
main.rs:7     childrenlist : [Rc<TreeNode<T>>]
main.rs:8 }
error: aborting due to previous error

如果我们用Vec 替换一个数组,代码就会编译。但是,该结构是不可变的,我不需要过度分配的 Vec

我听说在编译时可以有一个大小未知的结构字段,只要它是唯一的。我们该怎么做?

【问题讨论】:

  • 我认为要求是“最后一个”,但无论如何这里也是如此。我找到了reddit.com/r/rust/comments/357ji5/…
  • 在 Rust 中,数组 有一个固定的大小,在编译时就知道了。因此,您不需要“数组”。 &amp;[T]通常被称为slice,我不知道[T]的发音。
  • @Shepmaster 我猜那将是“未调整大小的数组”。

标签: rust


【解决方案1】:

Rust 没有可变长度(堆栈)数组的概念,您似乎在这里尝试使用它。

Rust 有几个不同的数组类型。

  • Vec&lt;T&gt;(“向量”):动态调整大小;在堆上动态分配。这可能是您想要使用的。使用Vec::with_capacity(foo) 对其进行初始化以避免过度分配(这将创建一个具有给定容量的空向量)。
  • [T; n] ("array"): 静态大小;住在堆栈上。您需要在编译时知道大小,所以这对您不起作用(除非我错误分析了您的情况)。
  • [T](“切片”):未调整大小;通常从&amp;[T] 使用。这是内存中某处的Ts 的连续集合的视图。您可以通过引用数组或向量来获取它(称为“获取数组/向量的切片”),甚至可以查看数组/向量的子集。由于未调整大小,[T] 不能直接用作变量(它可以用作未调整大小的结构的成员),但您可以从指针后面查看它。引用 [T] 的指针是 fat ;即他们有一个额外的长度字段。如果您想存储对现有数组的引用,&amp;[T] 会很有用;但我认为这不是你想在这里做的。

【讨论】:

  • 感谢您提到指向[T] 的指针的胖度。我认为这是一条缺失的信息,因为我在其他任何地方都没有看到。
【解决方案2】:

如果事先不知道列表的大小,有两种选择:

  1. &amp;[T] 这只是对您不拥有的一些内存的引用
  2. Vec&lt;T&gt; 这是你自己的存储。

这里的正确做法是使用Vec。为什么?因为您希望子列表(Rc 的数组)实际归 TreeNode 所有。如果您使用&amp;[T],则意味着其他人将保留该列表,而不是TreeNode。通过一些终生的技巧,您可以编写一些有效的代码,但您必须付出很大的努力才能取悦编译器,因为借用的引用必须至少与 TreeNode 一样有效。

最后,你问题中的一句话说明了一个误解:

但是,结构是不可变的,我不需要过度分配的 Vec。

您混淆了可变性和所有权。当然你可以有一个不可变的 Vec。似乎您想避免从堆中分配内存,但这是不可能的,正是因为您不知道子列表的大小。现在,如果您担心过度分配,可以使用 with_capacity()shrink_to_fit() 等方法微调矢量存储。

最后一点:如果您真的知道列表的大小,因为它在编译时是固定的,您只需要使用[T; n],其中n 是编译时已知的。但这和[T]不一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-11
    • 2021-12-23
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    相关资源
    最近更新 更多