Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between storing a Vec vs a Slice?

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?

  • Will using a Vec force the language to copy memory whenever I call Bar::new(vec![1, 2, 3, 4, 5])?
  • Will the contents of Vec be implicitly destroyed when the owner Bar goes out of scope?
  • Are there any dangers associated with passing a slice in by reference if it's used outside of the struct that it's being passed to?
like image 595
KChaloux Avatar asked Sep 14 '15 18:09

KChaloux


People also ask

What does VEC mean in Rust?

A contiguous growable array type, written as Vec<T> , short for 'vector'.

What is a slice in Rust?

A slice is a pointer to a block of memory. Slices can be used to access portions of data stored in contiguous memory blocks. It can be used with data structures like arrays, vectors and strings. Slices use index numbers to access portions of data. The size of a slice is determined at runtime.

What is a VEC u8?

Vec<u8> is like Box<[u8]> , except it additionally stores a "capacity" count, making it three machine words wide. Separately stored capacity allows for efficient resizing of the underlying array. It's the basis for String .


1 Answers

A Vec is composed of three parts:

  1. A pointer to a chunk of memory
  2. A count of how much memory is allocated (the capacity)
  3. A count of how many items are stored (the size)

A slice is composed of two parts:

  1. A pointer to a chunk of memory
  2. A count of how many items are stored (the size)

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.

like image 146
Shepmaster Avatar answered Jan 18 '23 21:01

Shepmaster