【发布时间】:2014-12-01 08:57:15
【问题描述】:
这段代码是怎么回事:
fn method1(a: &str) -> (String, String) {
let res = method2(a);
(res.val0(), res.val1())
}
错误是:
error: use of moved value res
我该如何解决?
【问题讨论】:
标签: rust
这段代码是怎么回事:
fn method1(a: &str) -> (String, String) {
let res = method2(a);
(res.val0(), res.val1())
}
错误是:
error: use of moved value res
我该如何解决?
【问题讨论】:
标签: rust
看起来method2() 返回一个不可复制的对象,而val0() 和val1() 方法通过值获取它们的目标:
struct SomeType { ... }
impl SomeType {
fn val0(self) -> String { ... }
fn val1(self) -> String { ... }
}
fn method2(a: &str) -> SomeType { ... }
fn method1(a: &str) -> (String, String) {
let res = method2(a);
(res.val0(), res.val1())
}
因为SomeType 不是自动可复制的,它将被移动到按值获取它的方法中,但是您尝试这样做两次,这是不合理的,并且编译器报告“使用移动值”错误。
如果您无法更改SomeType,并且它只有val0() 和val1() 方法,没有公共字段并且没有实现Clone。那你就不走运了。您将只能获得 val0() 或 val1() 方法的结果,但不能同时获得两者。
如果SomeType 也有返回引用的方法,像这样:
impl SomeType {
fn ref0(&self) -> &String { ... }
fn ref1(&self) -> &String { ... }
}
(&str 代替 &String 也可以)
然后你可以克隆字符串:
let res = method2(a);
(res.ref0().clone(), res.ref1().clone())
如果SomeType 提供某种解构功能就更好了,例如:
impl SomeType {
fn into_tuple(self) -> (String, String) { ... }
}
那么就直截了当:
method2(a).into_tuple()
如果SomeType本身就是一个二元元组,你甚至不需要into_tuple(),直接写method2()调用即可:
method2(a)
元组还为元组和元组结构提供tuple indexing syntax,而不是即将被弃用的tuple traits。也可以使用:
let res = method2(a);
(res.0, res.1)
如果SomeType 确实是一个相同大小的元组,那是多余的,但如果SomeType 是一个更大的元组,这是要走的路。或者你可以使用解构:
let (v1, v2, _) = method2(a); // need as many placeholders as there are remaining elements in the tuple
(v1, v2)
【讨论】:
method2返回一个元组(String, String, .....),从res.val0()和res.val1()方法调用可以看出。
val0() 和 val1() 方法添加到您想要的任何数据类型,@PaoloFalabela 在他的评论中完美地证明了这一点。