如何在容器内保存对不同元素的多个引用?

2024-01-21

考虑这个简单的例子:v: Vec<Vec<i32>>我想添加v[1] to v[0].

我什至没有考虑牺牲性能,因此克隆任何载体都不是一种选择。因此,无论我们如何精确地实现向量的加法,我们都需要内部同时引用v: &mut v[0] and &v[1]。显然这里的问题是索引借用了v和可变上下文中的索引借用v可变的,所以借用检查器不会允许这样做。

这个例子导致了一个更普遍的问题:我们如何保持同时引用不同的如果所有返回(可变)元素引用的方法(可变地)借用容器本身,那么容器的元素会怎样?

请注意,我确实理解问题的根源以及为什么在编译时借用检查器无法看到我们正在引用不同的元素。问题是我们如何告诉编译器我们正在做正确的事情而不牺牲性能和/或安全性?

目前我知道 3 种可能的解决方案,并且不会产生明显的性能开销:

  1. slice::split_at_mut是一个不错的解决方法,但不幸的是仅适用于顺序/切片式容器。请注意,该函数在实现中使用了不安全的代码。
  2. 使用迭代器:是的,我们可以保存从迭代器返回的同时引用,但在许多情况下使用迭代器是不正确的,例如,map: HashMap<i32, Vec<i32>>我想再次补充map[1] to map[0]。请注意(据我所知)迭代器也使用不安全代码(直接或间接)。
  3. 最后是适用于每个容器的解决方案:RefCell<T>,即将容器的元素包装在RefCell。 (嗯,或者Cell<T>在某些情况下)。但这有两个问题。首先是运行时借用检查的轻微性能开销。第二个是,例如,如果我正在编写一个返回容器的函数,我要么必须让调用者使用我的RefCell- 包装容器或复制整个容器以删除RefCell包装(有没有办法打开RefCell免费放在容器内?)再一次,RefCell使用不安全的代码。

所有这些解决方案都使用不安全的代码。这真的是唯一的方法吗?我也很确定有一个直接使用不安全代码的解决方案,但作为初学者,我有点害怕深入研究不安全的 Rust。不过,如果它恰好是一个好的解决方案,请指出我需要研究的主题。

还有其他解决方案吗?哪一种更实用?有不懂的地方或者理解错误的地方请大家指正。

Edit:正如斯文·马尔纳克(Sven Marnach)指出的那样,我的问题太宽泛,所以我正在缩小问题范围。
我有一个map: HashMap<i32, Vec<i32>>我想分配map[0] + map[1](逐元素加法)到map[0]性能开销为零。在这里,matiu 建议的重复索引并不是最佳选择,因为它会涉及对同一键的多次搜索。那么,有可能吗?如果不是,这种情况的最佳解决方案是什么?


所以目标是用 vec[0] + vec[1] 覆盖 vec[0] ?

我认为诀窍是使用 Vec 的索引,而不是保持引用打开。

这达到目标了吗?

fn main() {
    let mut vec = vec![
        vec![1, 2, 3],
        vec![10, 20, 30],
    ];
    let ln = vec[0].len();
    for i in 0..ln {
        vec[0][i] += vec[1][i];
    }
    println!("{:?}", vec);
}

我还想测试就地执行是否实际上比创建新数组更快。 “也许编译器足够聪明,可以重用内部内存”我想。事实证明编译器并不那么聪明。

带索引的 for 循环是最快的方法。

Code:

结果(在我的笔记本电脑上):

running 7 tests
test bench_create_new_array   ... bench:         230 ns/iter (+/- 0)
test bench_for_indexes        ... bench:         174 ns/iter (+/- 0)
test bench_new_array_borrow   ... bench:         231 ns/iter (+/- 0)
test bench_to_owned1          ... bench:       1,097 ns/iter (+/- 4)
test bench_to_owned_in_place  ... bench:         240 ns/iter (+/- 1)
test bench_to_owned_in_place2 ... bench:       1,080 ns/iter (+/- 159)
test bench_to_owned_in_place3 ... bench:       1,037 ns/iter (+/- 2)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在容器内保存对不同元素的多个引用? 的相关文章

随机推荐

  • Silverlight:在 XAML 中声明数据集合?

    我想在我的 Silverlight for Windows Phone 7 应用程序中声明一些数据 我不确定语法是什么 例如 public class Person public string Name get set public int
  • 如何在使用流读取文件时保留换行符 - java 8

    try Stream
  • 生成 M 个箱中 N 个球的所有排列

    我想生成一组排列n球进m垃圾箱 以下一组嵌套列表生成这些排列 n lt 3 m lt 4 v lt rep 0 m for i in n 0 for j in n sum i 0 for k in n sum i j 0 for l in
  • 敲除 javascript foreach 绑定

    我试图允许用户创建一个铸造并向该铸造对象添加一组类别 我试图使用淘汰赛的 foreach 绑定到类别数组 并让用户向铸造添加新类别 我创建了一个 jsfiddle 来说明我在这里试图解释的内容 http jsfiddle net msell
  • Ruby 中的大指数?

    我只是在做一些与大学相关的 Diffie Hellman 练习 并尝试使用 ruby 遗憾的是 Ruby 似乎无法处理大指数 警告 在 a b 中 b 可能太大 NaN 有什么办法解决吗 例如 特殊的数学课或类似的课程 附注这是有问题的代码
  • 获取 Azure 队列中的消息 ID

    有没有办法在将消息插入队列Azure后获取消息ID CloudStorageAccount storageAccount CloudStorageAccount parse storageConnectionString CloudQueu
  • 我可以克隆未来吗?

    我想为未来编写一些通用的重试逻辑 我知道具体的返回类型 并且想在未来重试相同的操作 我的代码只能访问未来 我不想将每个 fn 调用站点包装在闭包中以启用重新创建它 似乎 未来 是 fn args 的组合 并且当 await被调用后 它会运行
  • 如何解决“无法读取 null 的属性‘appendChild’”错误?

    我尝试使用下面的代码 它在我的网站上的幻灯片中添加按钮 window onload function loadContIcons var elem document createElement img elem src http arno
  • Django 模板看不到 CSS 文件

    我正在构建一个 django 应用程序 但无法获取模板来查看 CSS 文件 我的 settings py 文件如下所示 MEDIA ROOT os path join os path abspath os path dirname file
  • Spring Boot未加载application.dev.properties文件

    在我的项目中 我想使用环境特定的属性文件 例如 如果我将其运行到开发中 它应该使用 application dev properties 对于生产它应该使用 application prod properties 等等 我的资源文件夹中有以
  • 当内容较长时,itextsharp 不会创建新页面

    我尝试从 3 天开始寻找制作一份 pdf 文档的方法 如果有任何帮助 我将不胜感激 我有几个表单字段可以毫无问题地访问和填写 我想在此字段下方放置动态创建的表 该表可以足够长 可以包含多个页面 这是我的问题 我无法将此表添加到其下方带有表单
  • 使用上次响应中的数据预填写 Google 表单

    我正在构建一个 Google 表单 我是唯一使用的表单 我每天使用该表单两次 或多或少 我希望某些字段预先填写我上次给出的响应值 因为它们的值不会经常更改 我将我的回复保存在 Google 电子表格中 以便可以从那里获取它们 但我对 Goo
  • 渲染多对多字段

    我试图在模板中显示多个字段 但我得到的只是空白 我将其显示如下 for vehicle in vehicle features features li vehicle features li endfor 我的模型如下 class Vehi
  • 如何使用最新版本的 FFMPEG 在视频录制中创建时间间隙?

    我是论坛的新手 所以我希望我正确地提出了这个问题 我已经下载了最新版本的 FFMPEG 我想用它通过在其中插入时间间隙来修改现有视频 这就是我所说的时间间隔 如果我输入的视频持续 2 秒并以 FPS 10 录制 则其帧的时间戳将如下 0 1
  • 删除 apk 后,每当我启动调试时,它都会告诉我该包尚未安装

    我打开了模拟器 并使用命令提示符删除了我的应用程序 我没有关闭模拟器 然后我进入 Eclipse 并点击 调试 但没有将 apk 部署到模拟器 只是告诉我该包尚未在系统中注册 New package not yet registered w
  • gtk2hs:删除小部件后请求重新计算窗口大小

    我有一个带有三个条目小部件和一个按钮的窗口 我使用该按钮以编程方式删除其中一个小部件 问题是主窗口在被删除后不会改变其大小以适应新的布局 我可以想象我需要向主循环发送一些信号或事件 这会导致重新计算 但我一直无法找到这样的功能 这是一些示例
  • Django的bulk_create函数示例

    我试图理解 Django 中的bulk create 这是我试图转换的原始查询 for e in q msg Message objects create recipient number e mobile content batch co
  • 如何更改 TreeView 节点高度,在节点中绘制 3 条线

    我将 D7 与 TreeView 不是 VirtualTreeView 一起使用 如何更改节点高度以使用 OwnerDraw 并在节点矩形中绘制 3 或 5 或更多 行 文本 所以树应该看起来像这样 显示根节点 2 个节点 aaa 和 bb
  • 使用 PM2 运行自定义 npm 脚本

    我目前正在开发几个 Telegram 机器人 但我想将它们全部保存在同一个 git 存储库中 问题是 另一方面 我想将它们作为单独的进程运行 由于我使用的是 Telegraf 框架 因此要运行机器人 请执行以下操作 micro bot sr
  • 如何在容器内保存对不同元素的多个引用?

    考虑这个简单的例子 v Vec