Rust 如何打印可变借阅后的值?
我构造一个字符串,然后借用它做一些更改。然后,我想查看字符串是如何更改的,但无法打印出值:Rust 如何打印可变借阅后的值?,rust,borrow-checker,Rust,Borrow Checker,我构造一个字符串,然后借用它做一些更改。然后,我想查看字符串是如何更改的,但无法打印出值: let mut s1 = String::from("hello"); let s2 = &mut s1; s2.truncate(2); print!("{}", s1); println!("{}", s2); error[E0502]:无法将's1'作为不可变项借用,因为它也是作为可变项借用的 -->src/lib.rs:5:18 | 3 |设s2=&mut s1; |----可变借用发生
let mut s1 = String::from("hello");
let s2 = &mut s1;
s2.truncate(2);
print!("{}", s1);
println!("{}", s2);
error[E0502]:无法将's1'作为不可变项借用,因为它也是作为可变项借用的
-->src/lib.rs:5:18
|
3 |设s2=&mut s1;
|----可变借用发生在这里
4 | s2.截断(2);
5 |打印!(“{}”,s1);
|^^此处发生不可变借用
6 | println!(“{}”,s2);
|--稍后在此处使用的可变借用
<>我认为C++中的Road与C++类似,因此当
- 在任何给定的时间,可以有一个可变引用,也可以有任意数量的不可变引用
s1
,并通过s2
将其作为不可变变量借用。这很好,只要您不同时使用这两个。这里没有出现问题,因为您还没有对引用进行任何处理。当您强制同时激活这两个引用时,就会出现问题。当您在s2
超出范围(即上次使用之后)之前访问s1
时,会发生这种情况。看看这个:
让mut s1=String::from(“hello”);//--s1范围的开始--
设s2=&mut s1;//--s2范围的开始--
s2.截断(2);//s1在这里不能用作
//这违反了规则
打印(“{}”,s1);//--s1范围结束--
普林顿!(“{}”,s2);//--s2范围结束--
如您所见,由于代码的结构,必须同时激活s1
和s2
的作用域。如果要交换最后两行代码,请将代码更改为:
让mut s1=String::from(“hello”);//--s1范围的开始--
设s2=&mut s1;//--s2范围的开始--
s2.截断(2);//s1在这里不能用作
//这违反了规则
普林顿!(“{}”,s2);//--s2范围结束--
打印(“{}”,s1);//--s1范围结束--
然后,您的代码将按预期编译和运行。原因是当s2
的作用域处于活动状态时,您根本没有使用s1
。换句话说,上述代码的每一行都会发生以下情况:
s1
拥有新创建的字符串
s2
可变地借用字符串
s2
用于截断字符串
s2
用于打印字符串
。由于这是最后一次使用s2
,因此在这一行之后字符串的所有权回到s1
s1
用于打印字符串
我建议你花点时间看看铁锈书的“理解所有权”一章。我的建议是从头到尾通读整本书。它将使您对Rust作为一种语言及其生态系统有一个很好的理解。Rust的引用不像在其他语言(如C/C++/Java)中那样有效。Rust编译器在编译时确保内存安全,它通过使用“借用检查器”来实现这一点。借阅检查器遵守一组规则,您发布的代码违反其中一个规则 以下是铁锈书中的一条直截了当的信息,它解决了这一确切的情况:
- 在任何给定的时间,可以有一个可变引用,也可以有任意数量的不可变引用
s1
,并通过s2
将其作为不可变变量借用。这很好,只要您不同时使用这两个。这里没有出现问题,因为您还没有对引用进行任何处理。当您强制同时激活这两个引用时,就会出现问题。当您在s2
超出范围(即上次使用之后)之前访问s1
时,会发生这种情况。看看这个:
让mut s1=String::from(“hello”);//--s1范围的开始--
设s2=&mut s1;//--s2范围的开始--
s2.截断(2);//s1在这里不能用作
//这违反了规则
打印(“{}”,s1);//--s1范围结束--
普林顿!(“{}”,s2);//--s2范围结束--
如您所见,由于代码的结构,必须同时激活s1
和s2
的作用域。如果要交换最后两行代码,请将代码更改为:
让mut s1=String::from(“hello”);//--s1范围的开始--
设s2=&mut s1;//--s2范围的开始--
s2.截断(2);//s1在这里不能用作
//这违反了规则
普林顿!(“{}”,s2);//--s2范围结束--
打印(“{}”,s1);//--s1范围结束--
然后,您的代码将按预期编译和运行。Th
let mut s1 = String::from("hello");
{
let s2 = &mut s1;
s2.truncate(2);
} //--End of s2 scope
println!("{}", s1);