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());
}
最佳答案
在 Rust 中,大多数方法都采用 &self
- 对自己的引用。在大多数情况下,像 some_string.len()
这样的电话在内部“扩展”成这样的东西:
let a: String = "abc".to_string();
let a_len: usize = String::len(&a); // This is identical to calling `a.len()`.
但是,考虑对对象的引用:a_ref
,这是一个 &String
引用 a
. Rust 足够聪明,可以确定是否需要添加或删除引用,就像我们在上面看到的( 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 的评论是正确的:您正在迭代一个新向量,它包含的元素是 v
中元素的克隆。 。在您的 for
中迭代的项目循环不是 &Vec
, 这是一个 Vec
与 v
分开,因此迭代器失效不是问题。
关于您关于 Rust 提供的保证的问题,您会发现 Rust 的借用检查器可以很好地处理这个问题,没有任何附加条件。
如果你要 remove clone()
from the for
loop,但是,您会收到一条错误消息 use of moved value: '*v_ref'
,因为 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()
生成的迭代器中被不变地借用(它的类型签名为 fn iter(&self) -> Iter<T>
- 注意,它对向量进行了借用),并且不允许您根据 Rust 的借用检查器改变向量,直到迭代器被删除(在 for
循环的末尾)。但是,由于您可以对单个对象有多个不可变 引用,您仍然可以读取 for 循环中的向量,只是不能写入它。
如果您需要在遍历向量时改变向量的元素,您可以使用 iter_mut
。 ,一次返回对一个元素的可变引用,并允许您仅更改该元素。你仍然不能用 iter_mut
改变迭代向量本身。 ,因为 Rust 确保一次只有 一个 对象的可变引用,并确保在与该对象的不可变引用相同的范围内没有对该对象的可变引用。 p>
关于vector - 在迭代向量时推送到向量时,Rust 会保护我免受迭代器失效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49225860/