What's the difference between &Vec<i32> and &[i32]?

Hi,
I have this code following, I wonder why I can pass a &Vec to &[i32] and also what's the difference between these two.
I just started learning rust and I would be so happy if you can help me. Thanks!

fn f(v: &[i32]) {
    println!("{:?}", v);
}

fn g(v: &Vec<i32>) {
    println!("{:?}", v);
}

fn main() {
    let x = vec![1,2,3];
    f(&x);
    g(&x);
}
2 Likes

The differences are:

  1. Using &[u8] is more efficient.
  2. Using &[u8] allows you to pass more things than just vectors, including sub-slices of vectors and stack arrays.
  3. The &Vec<i32> type allows you to call .capacity() on the vector.
3 Likes

Can you explain more deeply? In my limited knowledge, [i32] means an array and Vec means an vector, they are different, &[i32] and &Vec are just references of the two. From what you said, I guess &Vec is simply the reference of Vec. Maybe you can teach me what's &[i32], why it's not simply the reference of the array [i32]? Thank you!

No, &[i32] means a slice (typically always written with ampersand). The thing called an array includes the size, e.g. [i32; 10] is an array of length 10.

Whenever you see the &[i32] type, it behaves as if you had the following struct:

// This is not quite valid syntax, just to illustrate.
struct &[i32] {
    first_element: *const i32,
    length: usize,
}

That is, it has a pointer to the first element and the length. To access the nth element, you take the memory location of the first element and add the index to it, which yields a pointer to the nth element.

It is possible to create a slice to anything that stores multiple elements sequentially in memory. For example:

  1. You can get an &[i32] that points to the entire contents of an Vec<i32>. This would be a pointer to the first element and use the vector's length as the length.
  2. You can get an &[i32] that points to a subset of a Vec<i32> with &the_vector[4..10]. This would be a pointer to the fifth element in the vector (starts from zero!) and the length would be six.
  3. Many other types store several elements in a sequence. E.g. you can get a slice that points into an array.
  4. You can create empty slices of length zero by writing &[].
  5. You can even create slices of a single item using std::slice::from_ref. This always results in a length of one.
8 Likes

What's very clear. Thanks really!

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.