rust - 由于对 `.into_iter()` 的这种隐式调用,对向量的可变引用被移动,但调用 `.into_iter()` 显式有效

标签 rust

这将失败:

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);
}
但这会过去:
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);
}
当我编译第一个时,它失败了:
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() 时,通过了。发生了什么?

最佳答案

我相信区别在于 reborrow , 在后一种情况下执行,但在前一种情况下不执行。
可变引用通常不是 Copy .这是设计使然,因为复制可变引用将允许可变别名。但是,问题是这是如何工作的:

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()应该无法通过“使用移动值”进行编译。然而它可以编译,脱糖版本也是如此。
它编译的原因是编译器自动进行重借,替换v&mut *v .换句话说。此转换在接收器( self )和函数参数上完成:
// 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),只要临时引用的生命周期比原始引用短,并且您不要在临时引用有效时使用原始引用。
您通常会注意到只有在失败的极少数情况下才会重新借款。 This answer用 serde 描述了这种情况,其中由于使用泛型而重新借用失败。
回到最初的例子,你的 for循环是重新借用失败的另一个例子。给定一个可变引用 arrfor &mut val in arr的区别和 for &mut val in arr.into_iter()是对 into_iter() 的显式调用被视为 (&mut *arr).into_iter()从而允许继续使用 arr循环后。裸体for不这样做,而 arr对象丢失。

关于rust - 由于对 `.into_iter()` 的这种隐式调用,对向量的可变引用被移动,但调用 `.into_iter()` 显式有效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68936034/

相关文章:

rust - 将数字格式化/转换为任何基数的字符串(包括十进制或十六进制以外的基数)

struct - 如何在不出现 "use moved value"错误的情况下绑定(bind)盒装结构的多个字段?

rust - 如何复制而不是借用 i64 到 Rust 的闭包中?

performance - 什么 Rust 结构使用 libsystem_m 中的 nearbyint?

rust - 找不到 crate peg_syntax_ext

rust - 如何修复 "cannot find derive macro in this scope"?

io - 使用 Read::read_to_string 从 TcpStream 读取会挂起,直到连接被远程端关闭

generics - 如何创建包含更高维度的代数矩阵的结构?

rust - 为什么存储返回值可以避免两次借用

rust - StructOpt - 如何为 Vec 提供默认值?