Rust教程经常提倡使用
fn myFunc( x : &Something ) -> ....
通过引用传递参数。这使得在调用网站上显然需要明确地获取值参考:
myFunc(&myValue).
但我查了一下,可以使用模式匹配中常用的'ref'关键字来做:
fn myFunc( ref x : Something ) -> ....
然后,我可以简单地通过
来调用它myFunc(myValue)
内存方面,这是否像我预期的那样工作,或者在调用myFunc之前将myValue复制到堆栈上然后获取对副本的引用?
答案 0 :(得分:12)
复制该值,然后引用该副本。
fn f(ref mut x: int) {
*x = 12;
}
fn main() {
let mut x = 42;
f(x);
println!("{:d}", x);
}
输出:42
答案 1 :(得分:5)
这两个函数都将x
声明为&Something
。不同的是,前者将引用或拥有的框作为参数,而后者则期望它是常规的堆栈值。举例说明:
struct Something;
fn by_reference(x: &Something) {
println!("{:?}", x); // prints "&Something""
}
fn on_the_stack(ref x: Something) {
println!("{:?}", x); // prints "&Something""
}
fn main() {
let value_on_the_stack: Something = Something;
let owned: ~Something = ~Something;
let borrowed: &Something = &value_on_the_stack;
// Compiles:
on_the_stack(value_on_the_stack);
// Fail to compile:
// on_the_stack(owned);
// on_the_stack(borrowed);
// Dereferencing will do:
on_the_stack(*owned);
on_the_stack(*borrowed);
// Compiles:
by_reference(owned);
by_reference(borrowed);
// Fails to compile:
// by_reference(value_on_the_stack);
// Taking a reference will do:
by_reference(&value_on_the_stack);
}
由于on_the_stack
接受一个值,它会被复制,然后副本会与形式参数(示例中为ref x
)中的模式匹配。该匹配将x
绑定到对复制值的引用。
答案 2 :(得分:3)
如果您调用类似f(x)
的函数,则x
始终按值传递。
fn f(ref x: int) {
// ...
}
相当于
fn f(tmp: int) {
let ref x = tmp;
// or,
let x = &tmp;
// ...
}
即。引用完全限于函数调用。
答案 3 :(得分:1)
如果该值未实现Copy
,则两个函数之间的差异将变得更加明显。例如,Vec<T>
并没有实现Copy
,因为这是一个昂贵的操作,相反,它实现了Clone
(需要特定的方法调用)。
假设这样定义了两种方法
fn take_ref(ref v: Vec<String>) {}// Takes a reference, ish
fn take_addr(v: &Vec<String>) {}// Takes an explicit reference
take_ref
将尝试在引用之前复制传递的值。对于Vec<T>
,这实际上是一个移动操作(因为它不会复制)。这实际上消耗了向量,这意味着以下代码将引发编译器错误:
let v: Vec<String>; // assume a real value
take_ref(v);// Value is moved here
println!("{:?}", v);// Error, v was moved on the previous line
但是,当引用是显式的时,如take_addr
,Vec
不会移动,而是通过引用传递。因此,此代码可以正常工作:
let v: Vec<String>; // assume a real value
take_addr(&v);
println!("{:?}", v);// Prints contents as you would expect