多次借用的借用错误

2024-04-04

我正在 Rust 中实现一个就地递归解析器,但遇到了一些借用错误。代码片段重现了问题,尽管它不是很有用

 use std::vec::Vec;

struct MyBorrows<'a> {
    val : &'a mut i32
}

impl <'a> MyBorrows<'a> {
    fn new(v : &'a mut i32) -> MyBorrows<'a> {
        MyBorrows { val : v }
    }
}

fn main() {
    let mut my_val = 23;
    let mut my_vec : Vec<Box<MyBorrows>> = Vec::new();
    my_vec.push(Box::new(MyBorrows::new(&mut my_val)));
    for i in [1..4].iter() {
        let mut last : &mut Box<MyBorrows> = my_vec.last_mut().unwrap();
        let mut new_borrow = Box::new(MyBorrows::new(last.val));
        my_vec.push(new_borrow);        
    }
}

这给了我以下错误:



error[E0499]: cannot borrow `my_vec` as mutable more than once at a time
  --> test.rs:20:9
   |
18 |         let mut last : &mut; Box = my_vec.last_mut().unwrap();
   |                                              ------ first mutable borrow occurs here
19 |         let mut new_borrow = Box::new(MyBorrows::new(last.val));
20 |         my_vec.push(new_borrow);
   |         ^^^^^^ second mutable borrow occurs here
21 |     }
22 | }
   | - first borrow ends here

error: aborting due to 3 previous errors

  

在我的实际情况中,向量用作堆栈来引用越来越深的组件struct我正在解析成.这是我在 C++ 中用于通用解析的常见模式,我试图在 Rust 中复制它,但我遇到了问题。任何帮助将不胜感激。


你试图做的事情是不合理的。您似乎正在尝试创建多个MyBorrows它们都可变地借用相同的值,并让它们同时存活(在向量中)。这样的设置正是 Rust 旨在防止的,因为这就是数据竞争的发生方式。

你可能想做的是im可变地借用一堆值,这是合法的。因此,在清理了不必要的可变借用之后,我将问题简化为:

struct MyBorrows<'a> {
    val : &'a i32
}

impl <'a> MyBorrows<'a> {
    fn new(v : &'a i32) -> MyBorrows<'a> {
        MyBorrows { val : v }
    }
}

fn main() {
    let my_val = 23;
    let mut my_vec = vec![];
    my_vec.push(Box::new(MyBorrows::new(&my_val)));
    for _ in 1..4 {
        let last = my_vec.last().unwrap();
        let new_borrow = Box::new(MyBorrows::new(last.val));
        my_vec.push(new_borrow);
    }
}

现在你会得到一个稍微不同的错误:

error[E0502]: cannot borrow `my_vec` as mutable because it is also borrowed as immutable
  --> test.rs:18:9
   |
16 |         let last = my_vec.last().unwrap();
   |                    ------ immutable borrow occurs here
17 |         let new_borrow = Box::new(MyBorrows::new(last.val));
18 |         my_vec.push(new_borrow);
   |         ^^^^^^ mutable borrow occurs here
19 |     }
   |     - immutable borrow ends here

error: aborting due to previous error

这个比较棘手,当你打电话时你必须意识到发生了什么my_vec.last()——它返回对 Vec 中现有内存的引用,阻止任何其他内容接触 Vec。目前在 Rust 中,该引用一直存在到当前块的末尾。为了解决这个问题,请将可变借用包含在其自己的块作用域中:

fn main() {
    let my_val = 23;
    let mut my_vec = vec![];
    my_vec.push(Box::new(MyBorrows::new(&my_val)));
    for _ in 1..4 {
        let new_borrow;
        {
            let last = my_vec.last().unwrap();
            new_borrow = Box::new(MyBorrows::new(last.val));
        }
        my_vec.push(new_borrow);
    }
}

现在,可变借用在推送发生之前结束,并且生命周期有效。希望在未来,我们将得到非词汇生命周期 https://github.com/rust-lang/rfcs/issues/811添加到语言中,这样编译器就可以发现我的第一个示例实际上是安全的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多次借用的借用错误 的相关文章

随机推荐

  • 建议对古式拼写进行其他查询(例如 Google 的 Did You Mean)

    我的客户有一个包含 400 年历史的房地产记录数据库 他们有兴趣根据他们的数据向用户提供替代拼写建议 我假设在这样的情况下 它会变成一个包含 Martin 行以及 Martyn 和 Martine 等建议的表 有谁知道可以索引其数据的第三方
  • Git - 删除像它一样的旧提交,并且它的更改从未发生过

    我想删除较旧的提交 因为我必须将其分成 2 个提交 所以变化是在a5b4cd与以下的变化相同2a0d40e a8bb836 2a0d40e Add sending a8bb836 Add parsing a5b4cbd Add sendin
  • 使用 Python 图像库 (PIL) 标准化一组图像的直方图(亮度和对比度)

    我有一个脚本 它使用 Google Maps API 下载一系列大小相等的方形卫星图像并生成 PDF 图像需要事先旋转 我已经使用 PIL 这样做了 我注意到 由于光线和地形条件不同 有些图像太亮 有些图像太暗 生成的pdf结果有点难看 在
  • Redis多插入问题

    我尝试多次插入 但它给了我错误 http pastie org 7337421 http pastie org 7337421 cat mass insert txt 3 r n 3 r nSET r n 3 r nkey r n 5 r
  • Ansible:SSH 错误:unix_listener:对于 Unix 域套接字来说太长

    这是一个已知问题 我找到了解决方案 但它对我不起作用 首先我有 fatal openshift node compute e50xx gt SSH Error ControlPath too long It is sometimes use
  • Maven Wagon 插件:wagon:upload 可以上传到多个位置吗?

    我正在调查Maven 旅行车插件 http mojo codehaus org wagon maven plugin 尝试将一些工件上传到远程 UNC Server 共享 servername share directory to put
  • 获取异步函数的 NULL 值(使用等待之后),然后更新为新值

    当我运行我的应用程序时 它会抛出很多错误 并且我的设备上会出现红色 黄色错误屏幕 它会自动刷新并向我显示预期的输出 从日志中我可以看到 首先我的对象返回为 null 随后以某种方式更新并获得输出 我最近开始了 Android 开发 Flut
  • 如何在android中处理搜索视图的后退按钮

    我开发了一个在操作栏中具有搜索视图的应用程序 当我完美搜索其过滤器时 我遇到了问题 但是当我按下后退按钮时 它仍然显示过滤器数据 所以我的问题是操作栏搜索的后退按钮的事件是什么看法 我的搜索视图代码是 SearchView searchVi
  • 具有架构组件的多模块导航

    所以我当前的应用程序中的模块有这样的结构 我还没有找到任何关于多模块导航的官方文档 但我发现了这个article https medium com hartwich daniel multi module navigation with t
  • 如何将列标题转换为贷款号码的行[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我陷入了无法旋转的境地 我有一个类似下面 temp 的表 使用sql server 2008 r2 Select LoanNumber 2
  • 维护和重用现有的 webdriver 浏览器实例 - java

    基本上每次我从 eclipse 运行 java 代码时 webdriver 都会启动一个新的 ie 浏览器并在大部分情况下成功执行我的测试 然而 我有很多测试要运行 而且 webdriver 每次都会启动一个新的浏览器会话 这很痛苦 我需要
  • Raspberry Pi 上的 Sqlite4java

    我想在 Raspberry Pi 上使用我的 java 项目 此代码依赖于 sqlite4java 它使用许多平台 包括 Arm 处理器 的本机实现link http code google com p sqlite4java downlo
  • 如何让 vscode 知道 SCM 何时可见?

    我想用 VScode 的键绑定制作切换键 使用 alt 1 到 5 切换资源管理器和搜索 scm 调试扩展 我可以找到 explorerViewletVisible 或 searchViewletVisible 但我找不到 scm 源代码控
  • 如何从 Angular 范围中排除元素?

    我的前提是错误的 虽然 AngularJS 确实减慢了速度 但这并不是因为我下面描述的问题 然而 正是 flim 对我的问题 如何从 Angular 范围中排除元素 的回答才证明了这一点 我正在构建一个网站 该网站使用 d3 Raphael
  • PhoneGap iOS 7 和 localStorage

    我目前正在构建一个 PhoneGap 3 3 0 iOS 应用程序 该应用程序使用 Ember js EmberData 和 LocalStorage 适配器来保存数据 读了一些文章后就像这个 StackOverflow 问题 https
  • 集合接口和WCF

    我正在使用 C 和 WCF 来做 Web 服务 我有一个实现 IEnumerable 的类的成员变量 我尝试通过执行以下操作将其序列化为我的数据合同的一部分 DataContract class Item DataMember privat
  • 约束消失的情况:更高等级类型的怪异

    下面描述的所有实验都是使用 GHC 8 0 1 完成的 这个问题是后续问题具有类型别名混淆的 RankNTypes https stackoverflow com q 40252867 2751851 那里的问题归结为像这样的函数类型 LA
  • 获取 i18next 翻译器 缺少密钥

    这是我第一次使用 i18next 我不知道如何让它发挥作用 这似乎是文档 http i18next com docs 对我来说是不完整的 这是我使用 i18next 的 HTML 代码
  • JDBC无法在openshift上连接mysql数据库

    我设法使用 phpMyAdmin 等在 OpenShift 上设置 MySQL 数据库 我被告知我的数据库的主机名和端口分别是 OPENSHIFT MYSQL DB HOST 和 OPENSHIFT MYSQL DB PORT 我将其放入
  • 多次借用的借用错误

    我正在 Rust 中实现一个就地递归解析器 但遇到了一些借用错误 代码片段重现了问题 尽管它不是很有用 use std vec Vec struct MyBorrows lt a gt val a mut i32 impl lt a gt