数组作为结构字段

时间:2015-05-15 15:08:56

标签: rust

我想在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

我听说有可能在编译时有一个大小未知的结构字段,前提是它是唯一的。我们怎么做呢?

2 个答案:

答案 0 :(得分:24)

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

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

  • Vec<T>(“vector”):动态大小;在堆上动态分配。这可能是你想要使用的东西。使用Vec::with_capacity(foo)对其进行初始化以避免过度分配(这会创建一个具有给定容量的空向量)。
  • [T; n](“array”):静态大小;生活在堆栈上。你需要在编译时知道大小,所以这对你不起作用(除非我错误地分析了你的情况)。
  • [T](“切片”):未标注;通常用于&[T]。这是对某个内存中T连续的连续视图的看法。您可以通过引用数组或向量(称为“获取数组/向量的切片”),甚至将视图转换为数组/向量的子集来获得它。由于未归档,[T]不能直接用作变量(它可以用作unsized struct的成员),但您可以从指针后面查看它。引用[T]的指针是 fat <​​/ em>;即他们有一个额外的场长。如果要存储对现有数组的引用,&[T]会很有用;但我不认为这就是你想要做的。

答案 1 :(得分:6)

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

  1. &[T]这只是对您不拥有的某段记忆的引用
  2. Vec<T> 您自己的存储空间。
  3. 这里正确的是使用Vec。为什么?因为您希望子列表(Rc的数组)实际归TreeNode所有。如果您使用&[T],则表示其他人将保留列表,而不是TreeNode。使用一些终身技巧,你可以编写一些有效的代码,但你必须走得很远才能取悦编译器,因为借用的引用必须至少与TreeNode一样长。

    最后,你问题中的一句话显示出一种误解:

      

    但是,结构是不可变的,我不需要一个过度定位的Vec。

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

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