如何在可变借用后打印出一个值?
How to print out a value after a mutable borrow?
我构造了一个字符串,然后借用它做一些修改。然后我想看看字符串是如何改变的,但我无法打印出值:
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
将相应改变。
Rust 的引用不像在 C/C++/Java 等其他语言中那样工作。 Rust 编译器在编译时确保内存安全,它通过使用 "borrow checker" 来实现。借用检查器遵守一套规则,而您发布的代码违反了其中一个规则。
这是来自 Rust 书籍的直接 quote,它解决了这种确切 情况:
- At any given time, you can have either one mutable reference or any number of immutable references.
首先创建一个可变变量 s1
,然后通过 s2
将其作为不可变变量借用。这很好,只要您不同时使用它们。这里没有出现问题,因为您还没有真正对引用做任何事情。当您强制这两个引用同时处于活动状态时,就会出现问题。当您在 s2
超出范围之前访问 s1
时会发生这种情况(那将是在它最后一次使用之后)。看看这个:
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 --
如您所见,由于代码的结构方式,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
println!("{}", s2); // -- End of s2 scope --
print!("{}", s1); // -- End of s1 scope --
然后您的代码将按预期进行编译和运行。原因是当 s2
的范围处于活动状态时,您根本没有使用 s1
。换句话说,这些事情发生在上面代码的每一行:
s1
拥有新创建的 String
s2
可变借用 String
s2
用于运行分类String
s2
用于打印String
。由于这是 s2
的最后一次使用,在此行之后 String
的所有权将返回到 s1
.
s1
用于打印String
.
我希望这能为您澄清情况。
我建议您花时间看看 Rust 书的 "Understanding Ownership" 章节 here。我的建议是从头开始阅读整本书。它会让您很好地理解 Rust 作为一种语言及其生态系统。
(我是问这个问题的人。)我喜欢@mrzenioszeniou 的回答,我对 不可变引用和可变引用不能同时激活 印象深刻.我也试过这段代码:
let mut s1 = String::from("hello");
{
let s2 = &mut s1;
s2.truncate(2);
} //--End of s2 scope
println!("{}", s1);
这里我把s2
作为&mut s1
带到一个新的子作用域,当作用域结束时,它不会影响s1的不可变借用。
我构造了一个字符串,然后借用它做一些修改。然后我想看看字符串是如何改变的,但我无法打印出值:
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
将相应改变。
Rust 的引用不像在 C/C++/Java 等其他语言中那样工作。 Rust 编译器在编译时确保内存安全,它通过使用 "borrow checker" 来实现。借用检查器遵守一套规则,而您发布的代码违反了其中一个规则。
这是来自 Rust 书籍的直接 quote,它解决了这种确切 情况:
- At any given time, you can have either one mutable reference or any number of immutable references.
首先创建一个可变变量 s1
,然后通过 s2
将其作为不可变变量借用。这很好,只要您不同时使用它们。这里没有出现问题,因为您还没有真正对引用做任何事情。当您强制这两个引用同时处于活动状态时,就会出现问题。当您在 s2
超出范围之前访问 s1
时会发生这种情况(那将是在它最后一次使用之后)。看看这个:
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 --
如您所见,由于代码的结构方式,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
println!("{}", s2); // -- End of s2 scope --
print!("{}", s1); // -- End of s1 scope --
然后您的代码将按预期进行编译和运行。原因是当 s2
的范围处于活动状态时,您根本没有使用 s1
。换句话说,这些事情发生在上面代码的每一行:
s1
拥有新创建的String
s2
可变借用String
s2
用于运行分类String
s2
用于打印String
。由于这是s2
的最后一次使用,在此行之后String
的所有权将返回到s1
.s1
用于打印String
.
我希望这能为您澄清情况。
我建议您花时间看看 Rust 书的 "Understanding Ownership" 章节 here。我的建议是从头开始阅读整本书。它会让您很好地理解 Rust 作为一种语言及其生态系统。
(我是问这个问题的人。)我喜欢@mrzenioszeniou 的回答,我对 不可变引用和可变引用不能同时激活 印象深刻.我也试过这段代码:
let mut s1 = String::from("hello");
{
let s2 = &mut s1;
s2.truncate(2);
} //--End of s2 scope
println!("{}", s1);
这里我把s2
作为&mut s1
带到一个新的子作用域,当作用域结束时,它不会影响s1的不可变借用。