我想在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
。
我听说有可能在编译时有一个大小未知的结构字段,前提是它是唯一的。我们怎么做呢?
答案 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)
如果您事先不知道列表的大小,您有两种选择:
&[T]
这只是对您不拥有的某段记忆的引用Vec<T>
您自己的存储空间。这里正确的是使用Vec
。为什么?因为您希望子列表(Rc
的数组)实际归TreeNode
所有。如果您使用&[T]
,则表示其他人将保留列表,而不是TreeNode
。使用一些终身技巧,你可以编写一些有效的代码,但你必须走得很远才能取悦编译器,因为借用的引用必须至少与TreeNode
一样长。
最后,你问题中的一句话显示出一种误解:
但是,结构是不可变的,我不需要一个过度定位的Vec。
你混淆了可变性和所有权。当然你可以有一个不可变的Vec。看起来你想避免从堆中分配内存,但这是不可能的,正是因为你不知道子列表的大小。现在,如果您关注过度分配,可以使用with_capacity()
和shrink_to_fit()
等方法微调矢量存储。
最后一点:如果您确实知道列表的大小,因为它在编译时是固定的,您只需要使用[T; n]
,其中n
是编译时已知的。但这与[T]
不一样。