某些语言(如Haskell)不区分传值和传递引用。然后,编译器可以使用启发式近似地选择最有效的调用约定。一个启发式示例是针对Linux x64 ABI:如果参数的大小大于16个字节,则将指针传递给堆栈,否则传递寄存器中的值。
在Rust中同时保留传值和传递引用(当然不可变)的概念有什么好处,并强制用户选择?
如果看到值被修改,那么传递值是传递引用+副本的语法糖吗?
答案 0 :(得分:9)
两件事:
换句话说,在Rust中,这两种形式具有不同的语义。但是,这并不排除进行优化。
答案 1 :(得分:0)
[已修改:已将exampled更改为在发布模式下工作]
这不是语法糖,正如人们可以通过查看生成的代码看到的那样。
鉴于这些功能:
fn by_value(v: (u64, u64)) -> u64 {
v.0 + v.1
}
fn by_ref(v: &(u64, u64)) -> u64 {
v.0 + v.1
}
然后如果一个是另一个的语法糖,我们希望它们生成相同的汇编代码,或至少相同的调用约定。但实际上,我们发现by_ref
在v
和rdi
个寄存器中传递了rsi
,而by_value
在v
中传递了指向rdi
的指针{1}}注册并且必须遵循该指针来获取值:(see details,使用释放模式):
by_value:
movq 8(%rdi), %rax
addq (%rdi), %rax
retq
by_ref:
leaq (%rdi,%rsi), %rax
retq