Can I efficiently return an object by value in Rust?

Yes, by all means, you should write

fn initialize() -> Vec<Vec<MyStruct>> { ... }

(By the way, a Vec is not that large – it’s only 3 pointer-sized integers)

Rust has RVO, and this is advertised in guides. You can see it yourself with this code:

#[inline(never)]
fn initialize() -> Vec<i32> {
    Vec::new()
}

fn main() {
    let v = initialize();
}

If you compile this program in release mode on the playground, outputting assembly, among everything else you will see this:

playground::initialize:
    movq    $4, (%rdi)
    xorps   %xmm0, %xmm0
    movups  %xmm0, 8(%rdi)
    retq

Vec::new() was inlined, but you can see the idea – the address for the fresh Vec instance is passed into the function in %rdi, and the function stores Vec fields directly into this memory, avoiding unnecessary copying through the stack. This is how it is called:

playground::main:
    subq    $24, %rsp
    movq    %rsp, %rdi
    callq   playground::initialize

You can see that eventually the Vec instance will be put directly into the stack memory.

Leave a Comment