Rust:更改通过引用传递的向量

问题描述 投票:0回答:1

这是一个向量的示例,该向量传递给一个函数,该函数将值相加并将相同的向量传递给另一个对其进行排序的函数。

fn bubble_sort(mut arr: Vec<i32>) {
    let mut swapped = true;
    while swapped {
        swapped = false;
        for i in 0..arr.len()-1 {
            if arr[i] > arr[i + 1] {
                let tmp = arr[i];
                let arr[i] = arr[i + 1];
                let arr[i + 1] = tmp;
                swapped = true;
            }
        }
    }
}

fn populate(n: i32, mut &factors: Vec<i32>) {
    factors.push(2);
    factors.push(2);
    factors.push(n);
    factors.push(41);
    bubble_sort(factors);
}

fn main() {
    let mut factors: Vec<i32> = Vec::new();
    populate(164, &factors);
    println!("Factors {:?}", factors);
}

编译器已尽力帮助我,但无济于事。你能帮忙吗?我知道有库排序方法,对我来说关键问题是更改向量值。

rust vector reference
1个回答
0
投票

让我们回顾一下错误。首先,我们有两个相同的。

error: expected a pattern, found an expression
 --> src/main.rs:8:21
  |
8 |                 let arr[i] = arr[i + 1];
  |                     ^^^^^^ arbitrary expressions are not allowed in patterns

error: expected a pattern, found an expression
 --> src/main.rs:9:21
  |
9 |                 let arr[i + 1] = tmp;
  |                     ^^^^^^^^^^ arbitrary expressions are not allowed in patterns

let
仅在声明新变量时使用。如果您只想分配给现有变量,则不要使用
let

// let arr[i] = arr[i + 1];
// let arr[i + 1] = tmp;
arr[i] = arr[i + 1];
arr[i + 1] = tmp;

我将跳过下一个错误并转到第四个错误。

error[E0308]: mismatched types
  --> src/main.rs:16:21
   |
16 | fn populate(n: i32, mut &factors: Vec<i32>) {
   |                     ^^^^^^^^^^^^  -------- expected due to this
   |                     |
   |                     expected `Vec<i32>`, found `&_`
   |
   = note: expected struct `Vec<i32>`
           found reference `&_`
help: to take parameter `factors` by reference, move `&` to the type
   |
16 - fn populate(n: i32, mut &factors: Vec<i32>) {
16 + fn populate(n: i32, factors: &Vec<i32>) {
   |

在 Rust 中,参数遵循

PATTERN: TYPE
语法。对于大多数参数,
PATTERN
是单个名称。
TYPE
完全确定您传递给函数的内容。您正在寻找一个需要引用的函数,所以让我们应用编译器的建议,暂时忽略
mut

// fn populate(n: i32, mut &factors: Vec<i32>) {
fn populate(n: i32, factors: &Vec<i32>) {

尝试再次编译,我们收到另一个错误。

error[E0308]: mismatched types
  --> src/main.rs:21:17
   |
21 |     bubble_sort(factors);
   |     ----------- ^^^^^^^- help: try using a conversion method: `.to_vec()`
   |     |           |
   |     |           expected `Vec<i32>`, found `&Vec<i32>`
   |     arguments to this function are incorrect
   |
   = note: expected struct `Vec<_>`
           found reference `&Vec<_>`
note: function defined here
  --> src/main.rs:1:4
   |
1  | fn bubble_sort(mut arr: Vec<i32>) {
   |    ^^^^^^^^^^^ -----------------

Rust 的借用模型分为三个级别:拥有的 (

T
)、可变引用 (
&mut T
) 和共享引用 (
&T
)。您可以将列表中较早的值转换为列表中较晚的值,但反之则不行。

在这里,您的

populate
函数具有
&Vec<i32>
(共享引用),而
bubble_sort
需要
Vec<i32>
(拥有值)。编译器建议使用
.to_vec()
,它会复制
Vec
。这将使代码编译,但它不会执行您想要的操作,因为
bubble_sort
将在新的独立值上运行。

您可以升级

populate
以获取拥有的
Vec<i32>
,但让我们降级
bubble_sort
以获取
&Vec<i32>

// fn bubble_sort(mut arr: Vec<i32>) {
fn bubble_sort(arr: &Vec<i32>) {

现在,当我们编译时,我们收到六个相同的错误,其中有两个建议修复。

error[E0596]: cannot borrow `*arr` as mutable, as it is behind a `&` reference
 --> src/main.rs:8:17
  |
8 |                 arr[i] = arr[i + 1];
  |                 ^^^ `arr` is a `&` reference, so the data it refers to cannot be borrowed as mutable
  |
help: consider changing this to be a mutable reference
  |
1 | fn bubble_sort(arr: &mut Vec<i32>) {
  |                      +++
error[E0596]: cannot borrow `*factors` as mutable, as it is behind a `&` reference
  --> src/main.rs:17:5
   |
17 |     factors.push(2);
   |     ^^^^^^^ `factors` is a `&` reference, so the data it refers to cannot be borrowed as mutable
   |
help: consider changing this to be a mutable reference
   |
16 | fn populate(n: i32, factors: &mut Vec<i32>) {
   |                               +++

这些都很容易理解。我们想要改变

Vec
,所以我们必须可变地借用它。应用这两项修复后,我们就只剩下一个错误了。

// fn populate(n: i32, factors: &Vec<i32>) {
fn populate(n: i32, factors: &mut Vec<i32>) {
// fn bubble_sort(arr: &Vec<i32>) {
fn bubble_sort(arr: &mut Vec<i32>) {

最后一个错误:

error[E0308]: mismatched types
  --> src/main.rs:26:19
   |
26 |     populate(164, &factors);
   |     --------      ^^^^^^^^ types differ in mutability
   |     |
   |     arguments to this function are incorrect
   |
   = note: expected mutable reference `&mut Vec<_>`
                      found reference `&Vec<_>`
note: function defined here
  --> src/main.rs:16:4
   |
16 | fn populate(n: i32, factors: &mut Vec<i32>) {
   |    ^^^^^^^^         ----------------------

请记住,我们在函数签名中将此参数从共享引用升级为可变引用,因此我们需要对调用站点执行相同的操作。

// populate(164, &factors);
populate(164, &mut factors);

而且它有效!您可以在 Playground here 上尝试完整的代码。


经常让人困惑的一件事是何时将

mut
放在变量名称之前以及何时将其放在变量名称之后。这篇文章对此进行了解释:在变量名之前和“:”之后放置“mut”有什么区别?

请务必阅读Book,它解释了 Rust 的所有这些要点,包括借用

© www.soinside.com 2019 - 2024. All rights reserved.