I would like to initialize a large object with a function. Currently I have:
fn initialize(mydata: &mut Vec<Vec<MyStruct>>) { /* ... */ }
I would prefer to have:
fn initialize() -> Vec<Vec<MyStruct>> { /* ... */ }
I've heard that C++ often implements return value optimization (RVO), if you are lucky and have a good compiler. Can we disable copying here and have it returned by a hidden pointer that is passed into the function? Is RVO part of the language or an optional optimization?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With