I would like to create a non binary tree structure in Rust. Here is a try
struct TreeNode {
tag : T,
father : Weak>,
If you don't know the size of the list in advance, you have two choices:
&[T]
which is just a reference to some piece of memory that you don't ownVec<T>
which is your own storage.The correct thing here is to use a Vec
. Why? Because you want the children list (array of Rc
) to be actually owned by the TreeNode
. If you used a &[T]
, it means that someone else would be keeping the list, not the TreeNode
. With some lifetime trickery, you could write some valid code but you would have to go very far to please the compiler because the borrowed reference would have to be valid at least as long as the TreeNode
.
Finally, a sentence in your question shows a misunderstanding:
However, the structure is immutable and I do not need an overallocated Vec.
You confuse mutability and ownership. Sure you can have an immutable Vec. It seems like you want to avoid allocating memory from the heap, but that's not possible, precisely because you don't know the size of the children list. Now if you're concerned with overallocating, you can fine-tune the vector storage with methods like with_capacity()
and shrink_to_fit()
.
A final note: if you actually know the size of the list because it is fixed at compile time, you just need to use a [T; n]
where n
is compile-time known. But that's not the same as [T]
.
Rust doesn't have the concept of a variable-length (stack) array, which you seem to be trying to use here.
Rust has a couple different array-ish types.
Vec<T>
("vector"): Dynamically sized; dynamically allocated on the heap. This is probably what you want to use. Initialize it with Vec::with_capacity(foo)
to avoid overallocation (this creates an empty vector with the given capacity).[T; n]
("array"): Statically sized; lives on the stack. You need to know the size at compile time, so this won't work for you (unless I've misanalysed your situation).[T]
("slice"): Unsized; usually used from &[T]
. This is a view into a contiguous set of T
s in memory somewhere. You can get it by taking a reference to an array, or a vector (called "taking a slice of an array/vector"), or even taking a view into a subset of the array/vector. Being unsized, [T]
can't be used directly as a variable (it can be used as a member of an unsized struct), but you can view it from behind a pointer. Pointers referring to [T]
are fat ; i.e. they have an extra field for the length. &[T]
would be useful if you want to store a reference to an existing array; but I don't think that's what you want to do here.