如果我执行以下操作,则会收到错误消息:
struct A;
struct B;
fn consume_a(_a: A) {}
fn consume_b(_b: B) {}
struct C(A, B);
impl C {
fn foo(self: Self) {
consume_a(self.0);
consume_b(self.1);
}
}
fn main() {
let c = Box::new(C(A, B));
// Consume internals
let _a = c.0;
let _b = c.1;
}
error[E0382]: use of moved value: `c`
--> src/main.rs:21:9
|
20 | let _a = c.0;
| -- value moved here
21 | let _b = c.1;
| ^^ value used here after move
|
= note: move occurs because `c.0` has type `A`, which does not implement the `Copy` trait
我可以做到这一点(消耗内部):
fn main() {
let c = Box::new(C(A, B));
c.foo();
}
上面的工作方式(c.foo()
)意味着我已经移出了盒装内容;怎么会发生这种情况? Box
文档中的所有API都没有显示我可以将所包含的值作为类型获取(即所有方法都返回&T
或&mut T
但不返回{{ 1}})
答案 0 :(得分:6)
正如您在方法中所看到的,移出结构体字段直接可以正常工作,但移出Box
中的结构字段将首先移出将Box
转换为临时变量,然后移出该临时变量的字段。因此,当您尝试移出第二个字段时,Box
已经被破坏,而且只是暂时的左侧,您无法使用。
您可以通过自己创建临时工具来完成这项工作:
let c2 = *c;
let _a = c2.0;
let _b = c2.1;
答案 1 :(得分:2)
启用非词汇生存期时,您的原始代码有效:
#![feature(nll)]
struct A;
struct B;
fn consume_a(_a: A) {}
fn consume_b(_b: B) {}
struct C(A, B);
impl C {
fn foo(self: Self) {
consume_a(self.0);
consume_b(self.1);
}
}
fn main() {
let c = Box::new(C(A, B));
// Consume internals
let _a = c.0;
let _b = c.1;
}
这表明原来的失败只是借入检查者的弱点。