Reputation: 4058
Rust provides a few ways to store a collection of elements inside a user-defined struct. The struct can be given a custom lifetime specifier, and a reference to a slice:
struct Foo<'a> {
elements: &'a [i32]
}
impl<'a> Foo<'a> {
fn new(elements: &'a [i32]) -> Foo<'a> {
Foo { elements: elements }
}
}
Or it can be given a Vec
object:
struct Bar {
elements: Vec<i32>
}
impl Bar {
fn new(elements: Vec<i32>) -> Bar {
Bar { elements: elements }
}
}
What are the major differences between these two approaches?
Vec
force the language to copy memory whenever I call Bar::new(vec![1, 2, 3, 4, 5])
? Vec
be implicitly destroyed when the owner Bar
goes out of scope? Upvotes: 31
Views: 10977
Reputation: 151
A Vec is a collection that can grow or shrink in size. It is stored on the heap, and it is allocated and deallocated dynamically at runtime. A Vec can be used to store any number of elements, and it is typically used when the number of elements is not known at compile time or when the number of elements may change during the execution of the program.
A slice is a reference to a contiguous sequence of elements in a Vec or other collection. It is represented using the [T] syntax, where T is the type of the elements in the slice. A slice does not store any elements itself, it only references elements stored in another collection. A slice is typically used when a reference to a subset of the elements in a collection is needed.
One of the main differences between a Vec and a slice is that a Vec can be used to add and remove elements, while a slice only provides read-only access to a subset of the elements in a collection. Another difference is that a Vec is allocated on the heap, while a slice is a reference and therefore has a fixed size. This means that a slice cannot be used to store new elements, but it can be used to reference a subset of the elements in a Vec or other collection.
Upvotes: 7
Reputation: 431589
A Vec
is composed of three parts:
A slice is composed of two parts:
Whenever you move either of these, those fields are all that will be copied. As you might guess, that's pretty lightweight. The actual chunk of memory on the heap will not be copied or moved.
A Vec
indicates ownership of the memory, and a slice indicates a borrow of memory. A Vec
needs to deallocate all the items and the chunk of memory when it is itself deallocated (dropped in Rust-speak). This happens when it goes out of scope. The slice does nothing when it is dropped.
There are no dangers of using slices, as that is what Rust lifetimes handle. These make sure that you never use a reference after it would be invalidated.
Upvotes: 63