Rust会保护我免受迭代器失效的影响吗?或者我对realloc
幸运吗?为&'a Vec<T>
返回的迭代器给出了什么保证?
fn main() {
let mut v = vec![0; 2];
println!("capacity: {}", v.capacity());
{
let v_ref = &mut v;
for _each in v_ref.clone() {
for _ in 0..101 {
(*v_ref).push(1); // ?
}
}
}
println!("capacity: {}", v.capacity());
}
答案 0 :(得分:4)
在Rust中,大多数方法都会将&self
- 引用转换为自我。在大多数情况下,内部some_string.len()
之类的呼叫会扩展&#34;这样的事情:
let a: String = "abc".to_string();
let a_len: usize = String::len(&a); // This is identical to calling `a.len()`.
但是,请考虑对对象的引用:a_ref
,它是引用&String
的{{1}}。 Rust非常聪明,可以确定是否需要添加或删除引用,如上所述(a
变为a
);在这种情况下,&a
会扩展为:
a_ref.len()
请注意,这基本上与原始示例相同,只是我们直接使用let a: String = "abc".to_string();
let a_ref: &String = &a;
let a_len: usize = String::len(a_ref); // This is identical to calling `a_ref.len();`. Since `a_ref` is a reference already, it doesn't need to be altered.
而不是a
的显式设置引用。
这意味着a
扩展为v.clone()
,类似地,Vec::clone(&v)
扩展为v_ref.clone()
,而且Vec::clone(v_ref)
为v_ref
(或,具体而言,&v
),我们可以将其简化为&mut v
。换句话说,这些调用等效 - 在对象的基本引用(Vec::clone(&v)
)上调用clone()
不会克隆引用,它克隆引用的对象。
换句话说,Tamas Hedgeus&#39;评论是正确的:您正在迭代一个新的向量,该向量包含&
中元素克隆的元素。在v
循环中迭代的项目不是for
,而是&Vec
与Vec
分开,因此迭代器失效不是问题
至于你关于Rust提供的保证的问题,你会发现Rust的借用检查程序处理得相当好而没有任何附加条件。
但如果您remove clone()
from the for
loop,,则会收到一条错误消息v
,因为use of moved value: '*v_ref'
被视为已被移动&#39;迭代它时进入v_ref
循环,不能用于函数的其余部分;为了避免这种情况,for
函数创建了一个迭代器对象,只有借用向量,允许您在循环结束后重用向量(并删除迭代器)。如果您在没有iter
抽象的情况下尝试iterating over and mutating v
,则错误会显示为v_ref
。 cannot borrow 'v' as mutable because it is also borrowed as immutable
在由v
生成的迭代器中不可靠地借用(其类型签名为v.iter()
- 注意,它使借用到向量),并且不允许你因为Rust的借用检查器而改变向量,直到迭代器被删除(在fn iter(&self) -> Iter<T>
循环结束时)。但是,由于您可以对单个对象进行多次不可变引用,因此您仍然可以从for循环中的向量读取,而不是写入它。
如果在迭代向量时需要改变向量的元素,可以使用iter_mut
,它将 mutable 引用返回到一个元素一段时间,让你只改变 的元素。你仍然无法使用for
来改变迭代向量本身,因为Rust确保一次只有一个可变引用对象,并确保没有可变引用与该对象的不可变引用在同一范围内的对象。