Optimization 我能否有效地按Rust中的值返回对象?
我想用一个函数初始化一个大对象。目前我有:Optimization 我能否有效地按Rust中的值返回对象?,optimization,rust,return-value-optimization,Optimization,Rust,Return Value Optimization,我想用一个函数初始化一个大对象。目前我有: fn initialize(mydata: &mut Vec<Vec<MyStruct>>) { /* ... */ } fn初始化(mydata:&mut-Vec){/*…*/} 我希望: fn initialize() -> Vec<Vec<MyStruct>> { /* ... */ } fn initialize()->Vec{/*…*/} 我听说如果你运气好,有一个好的编译
fn initialize(mydata: &mut Vec<Vec<MyStruct>>) { /* ... */ }
fn初始化(mydata:&mut-Vec){/*…*/}
我希望:
fn initialize() -> Vec<Vec<MyStruct>> { /* ... */ }
fn initialize()->Vec{/*…*/}
<>我听说如果你运气好,有一个好的编译器,C++经常实现返回值优化(RVO)。我们可以在这里禁用复制并通过传递到函数中的隐藏指针返回它吗?RVO是语言的一部分还是可选优化?是的,无论如何,您应该编写
fn initialize() -> Vec<Vec<MyStruct>> { ... }
如果您在发布模式下编译此程序,输出程序集等,您将看到:
playground::initialize:
movq $4, (%rdi)
xorps %xmm0, %xmm0
movups %xmm0, 8(%rdi)
retq
Vec::new()
是内联的,但是您可以看到这个想法-新鲜的Vec
实例的地址被传递到%rdi
中的函数中,并且该函数将Vec
字段直接存储到这个内存中,避免通过堆栈进行不必要的复制。这就是它的名称:
playground::main:
subq $24, %rsp
movq %rsp, %rdi
callq playground::initialize
您可以看到,
Vec
实例最终将直接放入堆栈内存。建议RVO触发大于指针的任何内容。但也有关于NRVO的问题。所以我想这完全取决于您如何实现initialize
。可能吧,但我发现LLVM IR的读取比程序集要困难得多,因为某些原因:(为此,我们只需要签名:define internal fastcc void@initialize(%)struct.collections::vec::vec[#3]“*noalias nocapture sret dereferenceable(24))unnamed_addr#0
。LLVM IR对于声明类似于C,因此该函数返回void
,并将指针(*
)带到结构集合::vec::vec
(为了更清楚起见,我使用了.[no\u mangle]
)这可能会显示传递一个指针,但如果您查看LLVM IR的末尾,您可能会看到内存块或类似内存块中有一个memcpy。我有一段代码,分配了一个256 int数组以返回,如果您查看IR的底部,您会看到从一个对象到另一个对象的副本。查看生成的ASM(在play.r-l.org上有beta版和夜间版),你可以看到mempcy@PLT在函数调用的底部。
playground::main:
subq $24, %rsp
movq %rsp, %rdi
callq playground::initialize