【问题标题】:Pass mut reference to a function, and get it back将 mut 引用传递给函数,然后将其取回
【发布时间】:2023-03-11 04:44:01
【问题描述】:

我从一个小时开始尝试编写代码示例,在String 中添加了一些空格。所以main借了一个String给添加空格的函数,然后,我想在main函数中取回字符串。

fn main() {
    ...
    let mut line = String::new();
    line = make_spaces(5, &mut line);
}

fn make_spaces(number: u8, string: &mut String) -> &mut String {
    for _ in 0..number {
        string.push(' ');
    }
    string
}

但是借用检查器给了我以下错误:

error[E0308]: mismatched types
  --> src/main.rs:14:12
   |
14 |     line = make_spaces(left_spaces, &mut line);
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |            |
   |            expected struct `String`, found `&mut String`
   |            help: try using a conversion method: `make_spaces(left_spaces, &mut line).to_string()`


我是rust 的新手,我知道我不懂借贷。但是我在网上搜了一下,还是不太明白。

据我了解,我将line 所有权授予make_spaces 函数,然后我(尝试)将string 的所有权还给main 函数。


你能告诉我我错在哪里吗?请问这个问题的解决方案是什么?我知道这是一个常见问题,但我在 stackoverflow 上没有看到任何简单的问题。

【问题讨论】:

  • 你为什么要返回一个参考?一个更有用的模式是什么都不返回。没有必要:调用者已经有了修改后的结构。
  • 你的函数返回一个mutable reference to string,但line的类型是mutable String。所以你试图分配一个不正确的类型。

标签: rust borrow-checker ownership


【解决方案1】:

有两种方法可以做你正在尝试的事情,但你正在混合使用这两种方法:

以可变参数作为参考

fn main() {
    let mut line = String::new();
    make_spaces(5, &mut line);
}

fn make_spaces(number: u8, string: &mut String) {
    for _ in 0..number {
        string.push(' ');
    }
}

在这种情况下,调用者会为您提供对结构的引用,以便您可以就地修改它。无需退货。

将参数移入函数中,然后返回修改后的值

fn main() {
    let mut line = String::new();
    line = make_spaces(5, line);
}

fn make_spaces(number: u8, mut string: String) -> String {
    for _ in 0..number {
        string.push(' ');
    }
    string
}

在这种情况下,字符串被移动到make_spaces 函数中,因此您需要通过返回将其移回调用方。

【讨论】:

  • 好的,谢谢您的回答。但是返回的字符串是副本,对吧?
  • 请注意,在 Rust 中,当我们说“某物是副本”时,我们的意思是它实现了 Copy 特征,而 String 没有。
  • 假设您真的在询问返回时是否复制字符串数据,答案是否定的:String 是一个包含指向堆上字符串数据的指针的结构,该指针是确实复制了,但数据本身没有(顺便说一句,当它作为参数传递时)。
  • 第二种情况下make_spaces定义中的mut放错了位置。它将在变量名称之前为mut string: String。如果没有这个修复,编译器会抛出一个错误。
  • Rust 中首选的方法是什么?
【解决方案2】:

您不必返回任何内容:您收到了对函数调用者已经拥有的结构的引用。

做事

fn main() {
    let mut line = String::new();
    make_spaces(5, &mut line);
    // use line here
}

fn make_spaces(number: u8, string: &mut String) {
    for _ in 0..number {
        string.push(' ');
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-25
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多