代码之家  ›  专栏  ›  技术社区  ›  Seph Reed

如何在铁锈中作为易变与不可变?

  •  0
  • Seph Reed  · 技术社区  · 6 年前

    我读过这些文件: https://doc.rust-lang.org/rust-by-example/scope/borrow/mut.html

    我也读过这个问题:( Cannot borrow immutable borrowed content as mutable )


    这些文档帮助我理解了如何将借款声明为可变的(我认为):

    let mut (part1, part2) = someTuple;
    

    但我还没能找到明确的说明,说明借款作为一种不变的东西是什么样子的。这是我的猜测:

    let (part1, part2) = someTuple;
    

    我知道这是一个超级基本的问题,但谷歌搜索它让我进入了解释的深层次,我仍在试图在最简单的语境中找到自己的方向。

    我该如何借用铁锈中的可变与不变?

    1 回复  |  直到 6 年前
        1
  •  4
  •   Ejdrien    5 年前
    let x = 0;
    let immutable_borrow = &x; //borrow as immutable
    
    //to borrow as mutable the variable needs to be declared as mutable
    let mut y = 1;
    let mutable_borrow = &mut y; //borrow as mutable
    

    附注1 :您可以在同一范围内借用不可变或可变的变量,这意味着您不能这样做:

    let mut x = 0;
    let immutable_borrow = &x;
    let mutable_borrow = &mut x;
    

    为什么?

    因为如果对同一个变量有可变和不可变的引用,那么该变量的数据可能会通过可变引用发生变化,这可能会导致很多问题。


    附注2 :你可以无限次不可变地借用一个变量,但你只能可变地借用一个变量一次。

    //You can do this
    let x = 0;
    let x1 = &x;
    let x2 = &x;
    //...
    
    //But you can't do this
    let mut y = 0;
    let y1 = &mut y;
    let y2 = &mut y; //won't compile if you use y1 after you declare y2
    

    为什么?

    如上所述。一个可变引用可能会更改所有其他可变引用指向的数据,而它们不知道。这可能会造成很多问题。但是有多个不可变的引用是可以的,因为数据不能意外地更改。

        2
  •  2
  •   Brian61354270    6 年前

    Ejdrien answers演示了可变借词和不可变借词之间的区别,但它并没有解决您问题中的副标题,即您正在执行借词,作为问题的一部分 pattern matching .

    当你写作的时候

    let (mut part1, mut part2) = someTuple;
    

    你是在约束 someTuple 对于可变变量 part1 和 part2 通过 移动 他们除非 某个元组 是 Copy 是的,变量 第一部分 和 第二部分 成为各自价值观的专属所有者。如果你试图访问 某个元组 后来通过写作。

    println!("{}", someTuple.0);
    

    您将收到来自借用检查器的编译错误,类似于

    error[E0382]: borrow of moved value: `someTuple.0`
     --> main.rs:6:20
      |
    4 |     let (mut part1, mut part2) = someTuple;
      |          --------- value moved here
    5 | 
    6 |     println!("{}", someTuple.0);
      |                    ^^^^^^^^^^^ value borrowed here after move
    
    

    在这个特定的上下文中,有两种方法可以通知编译器我们只想借用 某个元组 第一种是Ejdrien描述的技术,它显式地借用元组,并对随后产生的引用执行模式匹配:

    // Produce two mutable references
    let (part1, part2) = &mut someTuple;
    
    // Produce two immutable references
    let (part1, part2) = &someTuple;
    

    这种方法的问题在于,我们被迫借钱 每件事 以同样的方式。如果我们只需要对 someTuple.0 ,并希望检索 someTuple.1 作为副本,还是作为不可变的引用?对于这里的tuple示例,这似乎不太重要,但对于更复杂的模式匹配情况,拥有这种类型的控件更为重要。

    这给我们带来了第二种解决方案:绑定引用。我们可以写,而不是上面提到的

    // Produce two mutable references
    let (ref mut part1, ref mut part2) = someTuple;
    
    // Produce two immutable references
    let (ref part1, ref part2) = someTuple;
    

    在这里,我们明确说明了我们希望如何绑定模式匹配中的每个变量。这里的关键是,我们可以自由地混合可变和不变的借词,因此以下内容也完全有效:

    // Produce immutable reference and one mutable reference
    let (ref part1, ref mut part2) = someTuple;
    
    println!("{}", &someTuple.0); // Make a second immutable reference someTuple.0
    *part2 = ... // Mutate someTuple.1
    println!("{}", part1); // Continue using the immutable reference
    

    如果我们将上述内容与右侧的显式可变借阅进行交换,我们将再次收到借阅检查器的错误,因为同时存在可变和不可变引用:

    let (part1, part2) = &mut someTuple;
    
    println!("{}", &someTuple.0);
    *part2 = ... // Mutate someTuple.1
    println!("{}", part1);
    

    生产

    error[E0502]: cannot borrow `someTuple.0` as immutable because it is also borrowed as mutable
     --> main.rs:6:20
      |
    4 |     let (part1,part2) =&mut someTuple;
      |                        -------------- mutable borrow occurs here
    5 | 
    6 |     println!("{}", &someTuple.0);
      |                    ^^^^^^^^^^^^ immutable borrow occurs here
    ...
    9 |     println!("{}", part1);
      |                    ----- mutable borrow later used here
    
    error: aborting due to previous error
    
    
    推荐文章