Using structs in vector by value, not reference?


#1

In rust-sdl2 crate there are functions that use some objects by value. Therefore I need to use them like this:

let mut new_windows: Vec<Win> = Vec::new();
while system.windows.len() > 0 {
    let mut win: Win = system.windows.remove(0 as usize);
    if win.need_paint() {
        win = win.paint(renderer);
    }
    new_windows.push(win);
}
system.windows.append(&mut new_windows);

The “system.windows” is a Vec. Once more: functions can’t use references, and I’m giving them “win.field”, not the refs.
How can it be done more efficiently?

P.S.: And the compiler is complaining about vector.append():

error: use of unstable library feature ‘append’: new API, waiting for dust to settle


#2

Since you are replacing effectively replacing the vector with a new one, you can go to the extent of actually doing it:

use std::mem::swap;

//Pre-allocate enough space for all the windows
let mut windows = Vec::with_capacity(system.windows.len());

//Put the empty vector in `system`,
//and the populated one in `windows`
swap(&mut system.windows, &mut windows);

//Iterate over the windows, as values,
//and put them back into `system.windows`
for mut win in windows {
    if win.need_paint() {
        win = win.paint(renderer);
    }
    system.windows.push(win);
}

This uses Vec::with_capacity to avoid unnecessary reallocations, and by-value-iteration to avoid the overhead of remove. remove has to move every element one step towards the beginning, so it ends up being a lot of computation.This will not happen when iterating, since the vector will be completely consumed. This could even be extended to some sort of double buffering if drain was stable.

Oh, and about append. It’s also unstable, but we have extend which does the same thing, but less efficiently.


#3

Thank you! This works like a charm!