当不可变引用可以完成这项工作时,为什么我们需要 Rc

2023-12-22

为了说明必要性Rc<T>, the Book https://doc.rust-lang.org/book/ch15-04-rc.html呈现以下代码片段(剧透:它不会编译)以表明我们无法在没有Rc<T>.

enum List {
    Cons(i32, Box<List>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let a = Cons(5, Box::new(Cons(10, Box::new(Nil))));
    let b = Cons(3, Box::new(a));
    let c = Cons(4, Box::new(a));
}

然后它声称(强调我的)

我们可以改变的定义Cons来保存引用,但是我们必须指定生命周期参数。通过指定生命周期参数,我们将指定列表中的每个元素的生存时间至少与整个列表一样长。借用检查器不允许我们编译let a = Cons(10, &Nil);例如,因为临时Nil在 a 引用它之前, value 将被删除。

嗯,不完全是。以下代码片段在下编译rustc 1.52.1

enum List<'a> {
    Cons(i32, &'a List<'a>),
    Nil,
}

use crate::List::{Cons, Nil};

fn main() {
    let a = Cons(5, &Cons(10, &Nil));
    let b = Cons(3, &a);
    let c = Cons(4, &a);
}

请注意,通过引用,我们不再需要Box<T>间接保存嵌套List。此外,我可以指出b and c to a, 这使a多个概念所有者(实际上是借款人)。

问题:为什么我们需要Rc<T>不可变引用什么时候可以完成这项工作?


通过“普通”借用,您可以非常粗略地想到静态证明的按关系排序,其中编译器需要证明某物的所有者always在任何借用之前就已生效always所有借款都死后就死了(a owns String,它之前就复活了b哪个借用a, then b死了,然后a死亡;有效的)。对于很多用例来说,这是可以做到的,这是 Rust 使借用系统变得实用的洞察力。

在某些情况下,这无法静态完成。在您给出的示例中,您有点作弊,因为所有借用都有一个'static-寿命;和'static因此,项目可以在任何无限之前或之后“排序” - 所以实际上首先没有任何限制。当你采用不同的生命周期(许多List<'a>, List<'b>等)考虑在内。当您尝试将值传递给函数并且这些函数尝试添加项目时,此问题将变得明显。这是因为在函数内部创建的值在离开其作用域后(即当封闭函数返回时)将会消失,因此我们不能在之后保留对它们的引用,否则将会出现悬空引用。

Rc当一个人无法静态地证明谁是原始所有者,其生命周期在任何其他人之前开始并在任何其他人之后结束时(!),就会出现。一个典型的例子是从用户输入派生的图形结构,其中多个节点可以引用另一个节点。它们需要与它们在运行时引用的节点形成“生于之后,死于之前”的关系,以保证它们永远不会引用无效数据。这Rc是一个非常简单的解决方案,因为一个简单的计数器就可以表示这些关系。只要计数器不为零,some“生于之后,死于之前”的关系仍然活跃。这里的关键见解是,这并不重要按什么顺序节点的创建和消亡是因为any订单有效。只有两端的点(计数器为 0 的地方)实际上很重要,其间的任何增加或减少都是相同的(0=+1+1+1-1-1-1=0是相同的0=+1+1-1+1-1-1=0) The Rc当计数器达到零时被销毁。在图表示例中,这是当不再引用节点时。这告诉了它的主人Rc(最后一个节点指的是)“哦,事实证明I我是底层节点的所有者 - 没有人知道! - 我要摧毁它”。

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

当不可变引用可以完成这项工作时,为什么我们需要 Rc? 的相关文章

随机推荐

  • R删除每组数据框中的最后一行

    我想根据 max start date 删除 R 中每个组的数据帧中的最后一行 示例数据 id start date end date 1 2016 01 14 2016 02 14 1 2016 03 14 2016 08 05 2 20
  • 论坛的 LINQ 查询

    我正在为这个论坛编写代码 由于我是 LINQ 新手 所以当用户点击主页时遇到了这个问题 我想要一个显示论坛列表的表格 如下所示 Forum Topics count Posts count LastPostUserId LastPostTi
  • 使用 SAML 的 Okta 登录小部件

    我们有一个使用 Spring Boot AngularJS 开发的单一网页应用程序 我们希望集成 Okta 来进行身份验证部分 我已在 Okta 网站上创建了一个开发人员帐户 并使用 SAML 2 0 配置了一个应用程序 然后我将 Okta
  • 什么是 IndexOutOfRangeException / ArgumentOutOfRangeException 以及如何修复它?

    我有一些代码 当它执行时 它会抛出一个IndexOutOfRangeException 说 指数数组的边界之外 这是什么意思 我能做什么 根据所使用的类 它也可以ArgumentOutOfRangeException mscorlib dl
  • Linux C:如何知道默认的上网接口?

    我想找出正在使用的默认网络 我当前的方法是查找所有 IP 地址并将其与默认网关 IP 地址进行比较 但这听起来很愚蠢 正确的做法是什么 UPDATE 我想使用C程序 而不是通过命令 您可以尝试一种稍微脏一点但更简单的方法 cnicutar
  • select2 - 初始化选择错误

    使用 select2 插件时出现以下错误initSelection Error Uncaught Error No select2 compat initSelection是我收到的错误 希望有人帮助我整理inistselection is
  • Android LinearLayout 渐变背景

    我在将渐变背景应用于 LinearLayout 时遇到问题 从我读过的内容来看 这应该相对简单 但它似乎不起作用 作为参考 我正在 2 1 update1 上进行开发 header bg xml
  • 为什么我们需要 np.squeeze()?

    很多时候 数组被挤压np squeeze 在文档中 它说 从 a 的形状中删除单维条目 但我仍然想知道 为什么area 形状的零和无量纲条目 或者换句话说 为什么两者都a shape 2 1 and 2 exist 除了两者之间的数学差异之
  • 快速将 Range 转换为 [Int]

    如何将范围转换为数组 I tried let min 50 let max 100 let intArray Int min max 得到错误Range
  • 当http请求发送时,如何在react js中显示错误消息?

    你能告诉我当http请求发送时如何在react js中显示错误消息吗 我在要发送的nodejs中创建了一个服务400状态与error message 我想在以下位置显示此错误消息frontend app get a req res gt r
  • 在 .NET 中从 XML 文档中过滤元素的最简单方法

    假设我有以下文档
  • 为什么 glob lstat 匹配条目?

    调查行为这个问题 https stackoverflow com q 16443538 132382 我很惊讶地看到 perllstat http pubs opengroup org onlinepubs 009695399 functi
  • 在 Windows x64 和 Intel Fortran 中使用 f2py

    我试图通过 Intel Fortran 编译器在 Windows 8 x64 上使用 f2py 来实现 我尝试过两件事 1 通过 Windows 64x 安装程序安装 http www lfd uci edu gohlke pythonli
  • 将经过训练的 SVM 从 scikit-learn 导入 OpenCV

    我正在将使用支持向量机的算法从 Python 使用 scikit learn 移植到 C 使用 OpenCV 的机器学习库 我可以使用 Python 访问经过训练的 SVM 并且可以将 SVM 模型参数从 XML 文件导入 OpenCV 由
  • 简单的 FB 查询:画布应用程序中的 FB 登录屏幕?

    我的 Rails 应用程序在 FB 画布中运行 问题 如果用户未登录 Facebook 则会重定向到 Facebook 登录 身份验证页面 但是 这在画布中不起作用 因为 facebook 身份验证页面不允许将其自身加载到 iframe 中
  • 更改 OVH 上的 php 版本

    我的问题是我需要在远程服务器上将 php 版本从 4 4 9 更改为 5 5http www ovh com http www ovh com 但我似乎无法实现这个目标 我已尝试过推荐的步骤http www ovh com fr g1207
  • 如何录制视频并保持后台播放音乐?

    抱歉 如果这是重复的 但我找不到与此类似的问题 我有一个用 AVFoundation 制作的自定义相机 录音机 我想知道如何在录制视频时保持其他应用程序的音频运行 因为现在它会停止音频 甚至不暂停 然后录制视频 如果我的想法正确 可以通过添
  • MySQL 存储过程与复杂查询

    存储过程的性能如何 是否值得使用它们而不是在 PHP MySQL 调用中实现复杂的查询 存储过程会给您带来小小的性能提升 但大多数情况下 它们用于执行通过简单查询很难或不可能完成的任务 存储过程非常适合简化许多不同类型的客户端对数据的访问
  • cv2.imshow 崩溃 - libc++abi.dylib:因 NSException 类型的未捕获异常而终止

    我正在读取图像 然后使用 cv2 imshow 显示图像 但这会导致我的脚本崩溃 并显示以下堆栈跟踪 Code from flask restful import Resource from flask import jsonify req
  • 当不可变引用可以完成这项工作时,为什么我们需要 Rc

    为了说明必要性Rc