首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >由于对`.into_iter()`的隐式调用而移动了对向量的可变引用,但是调用`.into_iter()‘显式工作

由于对`.into_iter()`的隐式调用而移动了对向量的可变引用,但是调用`.into_iter()‘显式工作
EN

Stack Overflow用户
提问于 2021-08-26 09:32:11
回答 1查看 574关注 0票数 7

这将失败:

代码语言:javascript
复制
fn ppv(arr: &mut Vec<i32>) {
    if arr.len() <= 0 {
       return;
    }
    let mut pp: i32 = 0;
    for &mut val in arr {
        if val == pp {
            pp = val;
        }
    }
    println!("arr is {:?}", &arr);
}

但这会过去的:

代码语言:javascript
复制
fn ppv(arr: &mut Vec<i32>) {
    if arr.len() <= 0{
       return;
    }
    let mut pp: i32 = 0;
    for &mut val in arr.into_iter() {
        if val == pp {
            pp = val;
        }
    }
    println!("arr is {:?}", &arr);
}

当我编译第一个程序时,它失败了:

代码语言:javascript
复制
error[E0382]: borrow of moved value: `arr`
   --> src/main.rs:12:29
    |
2   | fn ppv(arr: &mut Vec<i32>) {
    |        --- move occurs because `arr` has type `&mut Vec<i32>`, which does not implement the `Copy` trait
...
7   |     for &mut val in arr {
    |                     --- `arr` moved due to this implicit call to `.into_iter()`
...
12  |     println!("arr is {:?}", &arr);
    |                             ^^^^ value borrowed here after move
    |

为什么会这样呢?它对它的解释是否不同?第一种情况将隐式调用into_iter(),它失败了,当我调用into_iter()时,它通过了。发生了什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-08-26 10:03:25

我认为区别在于在后一种情况下执行的再借,而不是前者。

可变引用通常不是Copy。这是设计上的,因为复制可变引用将允许可变的混叠。但问题是这是如何运作的:

代码语言:javascript
复制
fn foo(v: &mut Vec<i32>) {
    v.push(1);  // equivalent to Vec::push(v, 1)
    v.push(2);  // equivalent to Vec::push(v, 2)
}

如果对push()的第一次调用接收到v (而不是Copy ),那么对push()的第二次调用应该无法用“使用移动值”进行编译。然而,它也会编译,就像desugared版本一样。

它编译的原因是编译器自动执行重新借用,将v替换为&mut *v。换句话说。此转换是对接收方(self)和函数参数进行的:

代码语言:javascript
复制
// v is &mut Vec<i32>
v.push(1);        // treated as (&mut *v).push(1)
Vec::push(v, 2);  // treated as Vec::push(&mut *v, 2)

重用表单的编译是因为允许它基于现有的可变引用(例如,通过&mut r.some_field,其中r&mut SomeStruct)创建临时可变引用,只要临时引用比原始引用更短,并且在临时引用处于活动状态时不使用原始引用。

通常情况下,只有在很少情况下,当失败时才会注意到重新借款。这个答案用serde描述了这种情况,在这种情况下,由于使用泛型而导致重新借款失败。

为了回到原来的例子,您的for循环是另一个无法进行重借的例子。给定一个可变的引用arrfor &mut val in arrfor &mut val in arr.into_iter()之间的区别是,对into_iter()的显式调用被视为(&mut *arr).into_iter(),从而允许在循环之后继续使用arr。裸for不这样做,arr对象也丢失了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68936034

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档