0

I have a situation where I know how to initialise a vector, but I don't know the exact order of those elements.

let mut vector = todo!();
for (index, element) in &hash_map {
    vector[index] = element;
}

Now the problem is how to initialise the vector. The elements that it holds are not very lightweight, so I would prefer to cheat a little by creating an uninitialised vector:

let mut vector = Vec::with_capacity(size);
unsafe { vector.set_len(size) };

The problem is that when I later assign the value, I drop the previous element (which is uninitialised garbage) and panic:

vector[index] = element;

How can I assign an element to vector without triggering the default dropping behaviour?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
alagris
  • 1,838
  • 16
  • 31

1 Answers1

2

You can use pointer::write or ptr::write:

let mut vector: Vec<u8> = Vec::with_capacity(2);
unsafe {
    let base = vector.as_mut_ptr();
    base.offset(0).write(42);
    vector.set_len(1);
};
println!("{:?}", vector);

But it may be better to use MaybeUninit which is intended for this purpose.

See also:

Timmmm
  • 88,195
  • 71
  • 364
  • 509
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    Isn't it UB to use `set_len` before `write`? – Cerberus May 20 '21 at 17:59
  • 1
    @Cerberus ah, good call (["The elements at `old_len`..`new_len` must be initialized"](https://doc.rust-lang.org/1.52.1/std/vec/struct.Vec.html#safety-2)). I'm a bit surprised Miri didn't yell at me for that. – Shepmaster May 20 '21 at 18:04