你正在做的是在指针上进行字段访问 .
如果点左侧的表达式类型是指针,则会根据需要自动解除引用,以使字段访问成为可能
Rust如何评估借用内容上的字段访问表达式的示例:
let d = Data { /*input*/}
let body = (&d).body // -> (*&d).body -> d.body
let ref_body = &(&d).body // -> &(*&).body -> &d.body -> &(d.body)
注意:d仍然是借来的内容,只需要auto deref来访问这些字段 .
为什么要搬家?
考虑以下代码:
struct Data {
body: Vec,
id: i32,
}
fn p(mut d: &Data) {
let id = d.id;
}
此代码将按预期工作,此处不会有任何移动,因此您可以重用 d.id . 在这种情况下:
Rust将尝试复制 d.id 的值 . 由于 d.id 是 i32 并实现 Copy 特征,因此它会将值复制到 id .
考虑以下代码:
fn p(mut d: &Data) {
let id = d.id; // works
let body = d.body; // fails
}
此代码无效,因为:
Rust将尝试复制 d.body ,但 Vec 没有 Copy 特征的实现 .
Rust将尝试从 d 移动 body ,您将收到"cannot move out of borrowed content"错误 .
这对循环有何影响?
for表达式是一个语法结构,用于循环由std :: iter :: IntoIterator的实现提供的元素.for循环等效于以下块表达式 . 'label:用于iter_expr中的PATTERN {
/ 循环体 /
}
相当于{
let result = match IntoIterator :: into_iter(iter_expr){
mut iter =>'label:loop {
下一步让mut;
匹配Iterator :: next(&mut iter){
Option :: Some(val)=> next = val,
选项::无=>休息,
};
让PAT =下一个;
let()= {/ * loop body * /};
},
};
结果
}
这意味着您的向量必须具有 IntoIterator 的实现,因为 IntoIterator::into_iter(self) 期望 self 作为参数 . 幸运的是,两个impl IntoIterator for Vec,另一个是impl IntoIterator for &'a Vec存在 .
为什么会这样?
只是:
当您使用 &d.body 时,您的循环使用 IntoIterator 的 &Vec 实现 .
此实现返回一个指向矢量切片的迭代器 . 这意味着你将从你的向量中获得 reference of elements .
当您使用 d.body 时,您的循环使用 Vec 的 Vec 实现 .
此实现返回一个迭代器,它是一个消耗迭代器 . 这意味着你的循环将具有 ownership of actual elements ,而不是它们的引用 . 对于消费部分,此实现需要实际向量而不是引用,因此移动发生 .