For first question, in your example, there is an implicit assignment in function1
(to store the value of SomeStruct
somewhere so that Box::new
could read it), so there is no difference even in unoptimized mode.
As for your second question, well, there is no reason to allocate it on stack, you don't provide a reference to that value to a non-inlined function before boxing, so with optimizations, likely no stack allocation will happen (it's optimizations, you can never be sure).
Both functions have identical output code, but just to show, I compiled the Rust code to assembly with commentary (modified to actually write something, as allocating 0-bytes is not too useful).
pub struct SomeStruct {
value: i32,
other_value: i32,
}
pub fn function1() -> Box<SomeStruct> {
Box::new(SomeStruct {
value: 42,
other_value: 24,
})
}
pub fn function2() -> Box<SomeStruct> {
let foo = SomeStruct {
value: 42,
other_value: 24,
};
Box::new(foo)
}
example::function2:
# Stack frame for backtraces
push rbp
mov rbp, rsp
# Allocate 8 bytes (edi) with 4 bytes alignment (esi)
mov edi, 8
mov esi, 4
call __rust_allocate@PLT
# If null, out of memory error
test rax, rax
je .LBB1_2
# 64-bit assignment, this is pair of 24 and 42
movabs rcx, 103079215146 # 0x000000180000002A
# 64-bit write to heap allocated storage
# (x86_64 allows unaligned writes, not sure why compiler assumes this
# can be aligned to 8 bytes, when only 4 bytes alignment was requested)
mov qword ptr [rax], rcx
# end the function, output pointer is already correctly stored in rax
pop rbp
ret
# Out of memory somehow happened
.LBB1_2:
call alloc::oom::oom@PLT