Default value for `Option<&mut T>`?

Is there a way to avoid always allocating rd in line A?

pub fn main(
    render_data_opt: Option<&mut Vec<usize>>,
) {
    let mut rd = Vec::new(); // (A)
    let render_data = render_data_opt.unwrap_or_else(|| &mut rd);

    // (Use render_data)
}

Whether there are other ways to do this that don’t involve a Vec::new() call might depend on how render_data is actually used. Maybe the type that’s needed for the usage isn’t actually &mut Vec<usizize> because perhaps mutating – or at least growing – the Vec doesn’t even happen.

Regarding allocations, note that Vec::new() itself does not yet actually allocate anything. Only of the usage of render_data were to fill the Vec with data, e.g. with .push(…), would allocation happen, but if that is the case, I’d need to question what the imagined solution without any allocations is supposed to look like in the first place.

1 Like

If you're literally using Vec::new, like @steffahn said, don't worry about it -- it's cheap and doesn't allocate.

If the initialization is actually costly, you can do something like this.

pub fn weird_main(render_data_opt: Option<&mut Vec<usize>>) {
    let mut rd = Vec::new();
    let render_data = render_data_opt.unwrap_or_else(|| {
        rd.reserve(1_000_000);
        &mut rd
    });
}
2 Likes

Like this (if that didn’t cause lifetime issues):

pub fn main(
    render_data_opt: Option<&mut Vec<usize>>,
) {
    let render_data = render_data_opt.unwrap_or_else(|| &mut Vec::new());

    // (Use render_data)
}

In my code, render_data_opt is not based on Vec and an optional input&output parameter.

I may have to restructure my code so that it is moved in and returned (in addition to the actual result of the function, e.g. via a tuple).

I don't think you can initialize in a closure, but you can do this.

pub fn weird_main(render_data_opt: Option<&mut Vec<usize>>) {
    let mut rd;
    let render_data = match render_data_opt {
        Some(thing) => thing,
        None => {
            rd = Vec::with_capacity(1_000_000);
            &mut rd
        }
    };
}
4 Likes

Well, here's a closure-friendly way.

pub fn weird_main(render_data_opt: Option<&mut Vec<usize>>) {
    let mut rd = None;
    let render_data = render_data_opt.unwrap_or_else(|| {
        rd.insert(Vec::new())
    });
}
2 Likes

Both of these are great, thanks!

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.