为什么可变借入的顺序在Rust中很重要?

6equj5

这段代码编译(游乐场链接):

use std::collections::HashMap;

fn main() {
    let mut h = HashMap::<char, Vec<i32>>::new();
    h.insert('a', vec![0]);
    
    let first_borrow = h.get_mut(&'a').unwrap();
    first_borrow.push(1);
    let second_borrow = h.get_mut(&'a').unwrap();
    second_borrow.push(2);
}

使用借用(push()调用)更改代码的顺序...

let first_borrow = h.get_mut(&'a').unwrap();
let second_borrow = h.get_mut(&'a').unwrap();
first_borrow.push(1);
second_borrow.push(2);

...使其无法编译:

error[E0499]: cannot borrow `h` as mutable more than once at a time
 --> src/main.rs:8:25
  |
7 |     let first_borrow = h.get_mut(&'a').unwrap();
  |                        - first mutable borrow occurs here
8 |     let second_borrow = h.get_mut(&'a').unwrap();
  |                         ^ second mutable borrow occurs here
9 |     first_borrow.push(1);
  |     ------------ first borrow later used here

而且,使用first_borrow过去的实例化second_borrow也不会编译:

let first_borrow = h.get_mut(&'a').unwrap();
first_borrow.push(1);
let second_borrow = h.get_mut(&'a').unwrap();
second_borrow.push(2);
    
// ...
    
first_borrow.push(1);

考虑到文档中关于范围的说法,这令人惊讶。在编译的代码中,为什么我们那里也没有两个可变借项?

在这个例子中,编译,不会锈看到,之后let second_borrow = ...,有没有更多提及first_borrow的任何地方,因此它unborrows的可变借first_borrow,从而保留了单键借在整个范围的main()?!

奇金

在编译的代码中,为什么我们那里也没有两个可变借项?

简短的答案是,同一数据的两个可变借用不能同时在范围内,并且第一个示例不违反该限制。请注意,这是可变引用的“一个大限制”的推论,即“您只能在特定范围内对特定数据段进行一个可变引用”。请参阅“ Rust编程语言”中的参考和借阅”部分。

第一个示例编译是因为first_borrow超出范围才second_borrow进入范围。“超出范围”与在其余范围中未引用的变量同义。我不知道底层的细节,但是这就是我对这个示例的看法。

    // first_borrow comes into scope
    let first_borrow = h.get_mut(&'a').unwrap();
    first_borrow.push(1);
    // first_borrow goes out of scope
    // second_borrow comes into scope
    let second_borrow = h.get_mut(&'a').unwrap();
    second_borrow.push(2);
    // second_borrow goes out of scope

对于不编译你的第二个例子中,我们可以看到,作用域first_borrowsecond_borrow交叉。

    // first_borrow comes into scope
    let first_borrow = h.get_mut(&'a').unwrap();
    // second_borrow comes into scope
    let second_borrow = h.get_mut(&'a').unwrap();
    // !!! both first_borrow and second_borrow are in scope now !!!
    first_borrow.push(1);
    // first_borrow goes out of scope
    second_borrow.push(2);
    // second_borrow goes out of scope

在编译的示例中,Rust是否看到在让second_borrow = ...之后,再也没有提及first_borrow了,因此它不会借用first_borrow的可变借项,从而在main()的整个范围内保留一次借项? !

实际上,是的。我不认为这是无聊的。如上所述,我相信这个词first_borrow超出了范围。

例如,您可能会这样编写第一个示例。

    {
        let first_borrow = h.get_mut(&'a').unwrap();
        first_borrow.push(1);
    }
    {
        let second_borrow = h.get_mut(&'a').unwrap();
        second_borrow.push(2);
    }

当然,第二个示例不能以这种方式编写,因为借用是相互交叉的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么if语句中的表达式顺序很重要

为什么模板参数替换的顺序很重要?

为什么PHP的hash_equals()函数中的参数顺序很重要?

为什么在sed中这个转义字符类中顺序很重要?

为什么LET语句的顺序在此Entity Framework查询中很重要?

使用资源时,为什么在Rails route.rb中顺序很重要?

为什么NgModule导入顺序很重要?

为什么Owin Startup类中的auth中间件声明的顺序很重要?

为什么在简单的WebGL程序中绑定缓冲区的顺序似乎很重要?

为什么在Rails中强大的参数顺序很重要?

为什么与(tcp://)不同,zmq(inproc://)-connection的顺序很重要?

为什么在着色器中顺序很重要?

为什么cmp指令中的参数顺序很重要?

什么时候以及为什么顺序字段值在Firestore索引豁免中很重要?

为什么“或”条件中的语句顺序很重要?

为什么选择的顺序在正则表达式中很重要?

为什么在以下阻塞队列示例中调用notify()的顺序很重要?

为什么CSS中的注释很重要?

为什么应用建议的顺序很重要?

为什么方法声明中的顺序很重要?

为什么顺序在Observable.merge的用法中很重要?

为什么变量声明的顺序很重要?

为什么在MagicMock断言的Kwarg参数中顺序很重要?

从不可变类int继承的Python,为什么复制时参数的顺序很重要?

为什么先决条件的顺序在 makefile 中很重要?

Percona 查询指纹识别 - 为什么选择列中的顺序很重要?

为什么容器顺序在 yaml 文件中的 K8s-Pod 中很重要

为什么我在 Scalatest 套件中的 TestSuiteMixIn 特征中混合的顺序很重要?

为什么在这个笑话测试中它的功能顺序很重要?