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++类似,因此当 S/<代码>时,代码将相应地改变。

< P> RIST的引用不能像其他语言如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范围结束--
然后,您的代码将按预期编译和运行。原因是当
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);