如何循环实现into_iter的概念一直困扰着我,这个回答给我带来了更多的问题,比如重借的条款,除了一个地方之外,在生锈的正式文档中根本没有提到这个问题。
据我对这个评论的理解,当vec是一个可变的引用时,for i in vec.into_iter()实际上是场景后面的for i in (&mut *vec).into_iter()。
那么for i in vec呢,它实际上是i in vec.into_iter()吗?关于for循环是如何实现的,如何触发重新借款以及它是如何工作的,有什么地方有更详细的地方吗?
供参考的代码:
fn question1_1(vec: &mut [i32]) {
for &mut item in vec.into_iter() {
println!("{}", item);
}
for &mut item in vec { // --- `vec` moved due to this implicit call to `.into_iter()`
println!("{}", item);
}
vec; // Error: move occurs because `vec` has type `&mut [i32]`, which does not implement the `Copy` trait
}
pub fn main() {
let mut s = vec![1, 2, 3];
question1_1(&mut s);发布于 2022-05-16 12:27:28
for循环被设计成(通过检查HIR可以看到):
{
let _t = match IntoIterator::into_iter(iter) {
mut iter => loop {
match Iterator::next(&mut iter) {
None => break,
Some(i) => {
// Body
}
}
},
};
_t
}特别地,通过执行IntoIterator::into_iter(iterable)将可迭代转换为迭代器。每个特征,包括IntoIterator,都有一个隐藏的Self泛型参数,因此这实际上是IntoIterator::<_>::into_iter(iterable)。通过重新借用POV,这类似于:
fn foo<T>(v: T) {}
foo::<_>(iterable)确切的细节在可变引用有移动语义吗?中得到了解释,但总体思路是,它没有文档化。当前的工作方式是这样的,当编译器无法在没有推论的情况下确定某物是可变的引用时,它就不会被重新借用。因为_需要推理,所以不能再借用它。
接收方的工作方式不同(总是重新借用),因此iterable.into_iter()确实执行重借。事实上,这种行为与自动裁剪有关,而不是重新借款。另见铁锈的自动解除规则是什么?。
发布于 2022-05-16 13:29:41
除了在操场上使用HIR来检查如何在场景后面运行for循环之外,这里是关于for循环是如何去糖化的官方文档。
从文档给出的示例中,值( vec类型)被传递到IntoIterator::into_iter() IntoIterator::into_iter(values)中,这与作为方法values.into_iter()调用不同。
let values = vec![1, 2, 3, 4, 5];
for x in values {
println!("{}", x);
}脱糖
let values = vec![1, 2, 3, 4, 5];
{
let result = match IntoIterator::into_iter(values) {
mut iter => loop {
let next;
match iter.next() {
Some(val) => next = val,
None => break,
};
let x = next;
let () = { println!("{}", x); };
},
};
result
}https://stackoverflow.com/questions/72258925
复制相似问题