有时我必须采取长序列表达的信息,例如:
f1(f2(f3).f4(x,f5(y,z))).f6().f7()
(不一定是,你不想重复的任何长序列)。我可能需要多次引用它,其他代码介于两者之间。像这样:
fn myfunc(v: &T) -> X {
match v.func(func(v.func().func())).func() {
...
}
.. other stuff ..
match v.func(func(v.func().func())).func() {
...
}
}
该值不可移动,因此我无法将其分配给变量,然后像其他语言一样引用变量两次,所以基本上我发现自己多次编写相同的函数调用序列。我试过这样的事情
let x = &( ... )
然后使用此
*x
但这没有用。我想我可以使用一个宏,但是每次都会重新计算它(因为大多数函数调用只是编译器和类型系统的糖,所以它不会太糟糕),但是那个'到目前为止,我已经解决了这个问题。还有另一种方式吗?
答案 0 :(得分:1)
如果值不是Copy
,那么您需要复制它,或者通过引用传递。例如。假设它正在计算T
类型的值。我想你目前遇到的问题是
fn foo(x: T) { ... }
fn bar(x: T) { ... }
let your_thing = f1(f2(f3).f4(x,f5(y,z))).f6().f7();
foo(your_thing);
bar(your_thing); // error: use of moved value
正确的解决方法是将foo
行更改为
fn foo(x: &T) { ... }
foo(&your_thing);
或foo
对foo(your_thing.clone())
的调用(如果T
为Clone
)。您可以通过考虑foo
所需的所有权T
来决定哪一个是合适的:如果它需要完全所有权(例如将其传递给不同的任务),则应该按值{foo(x: T)
来获取它。 1}};另一方面,如果它只需要查看数据(即没有所有权),那么请参考foo(x: &T)
。
有关移动和复制的一些背景信息,另请参阅"Moves vs Copy in Rust"。它包括对&(...)
+ *x
解决方案不起作用的原因的解释:不能从引用后面移出(尽管在这种情况下它永远不会起作用,因为移出两次无论如何都是非法的。)
同样的推理适用于模式匹配:如果您只需要参考,您可以通过ref
参考感兴趣的值。例如。想象你正在计算Option<T>
。
let x = v.func(func(v.func().func())).func()
match x {
Some(ref y) => { /* y is a &T */ ... }
None => { ... }
}
// the last `match` can move `x`
match x {
Some(y) => { /* y is a T */ ... }
None => { ... }
}
如果第一个匹配确实需要x
某些部分的所有权,您可以clone
x
本身,也可以只匹配与ref
匹配后需要的部分。