3

I am trying to populate a vector after initialising it with with_capacity() as the number of elements is known prior to its creation and it seems more efficient with it.

The following code does NOT populate with random values AT ALL: println!("{}", v.len()); outputs zero.

use rand::Rng;

fn main() {
    const NUMBER_OF_RANDOM_NUMBERS: usize = 10;

    let mut v = Vec::with_capacity(NUMBER_OF_RANDOM_NUMBERS);

    for i in &mut v {
        *i += rand::thread_rng().gen_range(1, 2^32);
    }

    println!("{}", v.len());
}

My thinking is after let mut v = Vec::with_capacity(NUMBER_OF_RANDOM_NUMBERS) a brand new vector gets initialised with 10 zeros and then using rand::thread_rng().gen_range(1, 2^32) to insert, or should I say, add a random number to each zero.

Am I missing something here?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Julia O
  • 221
  • 2
  • 13
  • Capacity =/= length. I cannot find the duplicate right now. – Boiethios Mar 14 '19 at 13:00
  • 2
    `gen_range(1, 2^32);` does not do what you think it does (xor vs pow) – hellow Mar 14 '19 at 13:03
  • 1
    Take a look at the implementation for [`Vec::with_capacity(usize)`](https://doc.rust-lang.org/src/alloc/vec.rs.html#356-361), it sets the `len` to 0, therefore making it UB to access any value in the `Vec` – Optimistic Peach Mar 14 '19 at 13:48
  • *it seems more efficient* — yes, which is why `Iterator::collect` makes sure to allocate the correct space up front. Use one of the solutions from [How do I generate a vector of random numbers in a range?](https://stackoverflow.com/q/48218459/155423). These are additionally efficient because they do not create the RNG multiple times and do not repeatedly generate the range to pick inside. – Shepmaster Mar 14 '19 at 14:21
  • @hellow - Thank you very much for pointing that out. https://stackoverflow.com/questions/51208703/how-to-raise-a-number-to-a-power tells me exactly that. – Julia O Mar 15 '19 at 04:14

1 Answers1

7

with_capacity does not initialize the values of the vector, it just allocates space for them. From the documentation:

It is important to note that although the returned vector has the capacity specified, the vector will have a zero length. For an explanation of the difference between length and capacity, see Capacity and reallocation.

This means that when your loop code is executed, there are no items in the vector, and therefore it loops a total of zero times. Resulting in no change in the vector.

Marcus
  • 3,216
  • 2
  • 22
  • 22