首页 > 解决方案 > 如何在可变借用后打印出一个值?

问题描述

我构造了一个字符串,然后借用它进行一些更改。然后我想看看字符串是如何更改的,但我无法打印出该值:

let mut s1 = String::from("hello");
let s2 = &mut s1;
s2.truncate(2);
print!("{}", s1);
println!("{}", s2);
error[E0502]: cannot borrow `s1` as immutable because it is also borrowed as mutable
 --> src/lib.rs:5:18
  |
3 |     let s2 = &mut s1;
  |              ------- mutable borrow occurs here
4 |     s2.truncate(2);
5 |     print!("{}", s1);
  |                  ^^ immutable borrow occurs here
6 |     println!("{}", s2);
  |                    -- mutable borrow later used here

我认为 Rust 中的借用类似于 C++,因此何时s1更改s2会相应更改。

标签: rustborrow-checker

解决方案


Rust 的引用不像在 C/C++/Java 等其他语言中那样工作。Rust 编译器在编译时确保内存安全,它通过使用“借用检查器”来做到这一点。借用检查器遵守一组规则,而您发布的代码违反了其中一个规则。

这是 Rust 书中的直接引述,它解决了这种确切情况:

  • 在任何给定时间,您都可以拥有一个可变引用或任意数量的不可变引用。

首先,您创建一个可变变量s1,并将其作为不可变的 via 借用s2。这很好,只要您不同时使用它们。问题不会出现在这里,因为您还没有真正对引用做任何事情。当您强制这两个引用同时处于活动状态时,就会出现问题。当您访问s1之前s2超出范围时会发生这种情况(那将是在它最后一次使用之后)。看看这个:

  let mut s1 = String::from("hello"); // -- Start of s1 scope --
  let s2 = &mut s1;                       // -- Start of s2 scope --
  s2.truncate(2);                         // s1 may not be used here as
                                          // that breaks the rules
  print!("{}", s1);                   // -- End of s1 scope --
  println!("{}", s2);                     // -- End of s2 scope --

如您所见,由于代码的结构方式,范围s1s2必须同时处于活动状态。如果要交换最后两行代码,请将代码更改为:

  let mut s1 = String::from("hello"); // -- Start of s1 scope --
  let s2 = &mut s1;                       // -- Start of s2 scope --
  s2.truncate(2);                         // s1 may not be used here as
                                          // that breaks the rules
  println!("{}", s2);                     // -- End of s2 scope --
  print!("{}", s1);                   // -- End of s1 scope --

然后您的代码将按预期编译和运行。原因是虽然s2' 的范围是活动的,但你根本没有使用s1。换句话说,这些事情发生在上述代码的每一行:

  1. s1拥有新创建的String
  2. s2可变地借用String
  3. s2用于截断String
  4. s2用于打印String. 由于这是最后一次使用s2,在这条线的所有权String归回之后s1
  5. s1用于打印String.

我希望这可以为您澄清情况。

我建议您花点时间在此处查看 Rust 书籍的“了解所有权”一章。我的建议是从头开始阅读整本书。它会让你很好地理解 Rust 作为一门语言及其生态系统。


推荐阅读