如何解决 Rust 中可变引用的生命周期错误?

2023-12-07

我不确定为什么以下代码无法编译。

use std::cmp::Ordering;

struct MyItr<'a> {
    cur: &'a i32,
}

impl<'a> Ord for MyItr<'a> {
    fn cmp(&self, other: &MyItr) -> Ordering {
        self.cur.cmp(&other.cur)
    }
}

impl<'a> PartialOrd for MyItr<'a> {
    fn partial_cmp(&self, other: &MyItr<'a>) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a> PartialEq for MyItr<'a> {
    fn eq(&self, other: &MyItr) -> bool {
        self.cur == other.cur
    }
}

impl<'a> Eq for MyItr<'a> {}

fn f0<'a>(t0: &'a mut MyItr<'a>, t1: &'a mut MyItr<'a>, i: &'a i32) {
    let t = std::cmp::max(t0, t1);
    t.cur = i;
}

fn f1() {
    let i0 = 1;
    let i1 = 2;
    let mut z0 = MyItr { cur: &i0 };
    let mut z1 = MyItr { cur: &i1 };

    let i2 = 3;
    f0(&mut z0, &mut z1, &i2);
}
$ cargo build
   Compiling foo v0.1.0 (file:///private/tmp/foo)
error: `z1` does not live long enough
  --> lib.rs:40:1
   |
39 |     f0(&mut z0, &mut z1, &i2);
   |                      -- borrow occurs here
40 | }
   | ^ `z1` dropped here while still borrowed
   |
   = note: values in a scope are dropped in the opposite order they are created

我的理解是借用的参考资料z0 and z1一旦获得支持f0调用结束。然而,编译器似乎假设借用的引用不受支持。

$ cargo --version
cargo 0.20.0-nightly (41e490480 2017-05-16)

这里有两个问题。首先是您过度指定了生命周期,造成了编译器无法处理的情况。

fn f0<'a>(t0: &'a mut MyItr<'a>, t1: &'a mut MyItr<'a>, i: &'a i32)

您已经告诉编译器所有参数都必须是指针the same寿命。编译器可以缩小重叠的生命周期,但在这种情况下这没有帮助。您已指定指向MyItrs 与它们指向的事物具有相同的生命周期,and外部指针是可变的。

第二个问题是(即使在解决这个问题之后),您尝试做的事情是完全不安全的,并且会导致悬空指针。

这是一个more最小的例子:

struct S<'a> {
    ptr: &'a i32,
}

fn f<'b>(t: &'b mut S<'b>, new_ptr: &'b i32) {}

fn main() {
    let i0 = 1;
    let mut s = S { ptr: &i0 };

    let i1 = 2;
    f(&mut s, &i1);
}

What is 'b?嗯,编译器可以only生命周期很窄,所以通常你只会考虑你想要通过的所有事物的生命周期并选择最短的一个。在这种情况下,这将是i1。所以,它必须缩短寿命&s。指针的生命周期s本身不是问题(你可以缩小借用的时间),但缩小内部生命周期(用于借用的生命周期)ptr field) is一个问题。

如果编译器缩短了生命周期s.ptr,然后你就可以存储&i1在那个领域。s期望s.ptr超越自身,但这将不再是真的:i1 will 被摧毁 before s是,意思是s.ptr将包含一个悬空指针。和铁锈will not允许这种情况发生。

结果,铁锈can't narrow s的内在'a一生...但如果它不能缩小范围,那就意味着'b必须是完整的、未缩小的'a。但是等等,这意味着'b比生命周期长s itself and i1。那是不可能的。

因此失败了。

该解决方案需要两件事。首先,您不需要过度指定生命周期。其次,您需要确保存在一些有效的生命周期at all;对于您的原始代码,这意味着移动i2 above z0 and z1所以它比它们更长寿。就像这样:

fn f0<'a>(t0: &mut MyItr<'a>, t1: &mut MyItr<'a>, i: &'a i32) {
    let t: &mut MyItr<'a> = std::cmp::max(t0, t1);
    t.cur = i;
}

fn f1() {
    let i0 = 1;
    let i1 = 2;
    let i2 = 3;
    let mut z0 = MyItr { cur: &i0 };
    let mut z1 = MyItr { cur: &i1 };

    f0(&mut z0, &mut z1, &i2);
}

经验法则:不要到处乱发垃圾邮件。仅对应该相同的事物使用相同的生命周期。

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

如何解决 Rust 中可变引用的生命周期错误? 的相关文章

随机推荐

  • 以对象引用作为键的映射?

    我有一个存储有关特定实例的信息的对象 为此 我想使用Map 但由于键不是通过引用的 它们不是 对吧 而是作为由getHashCode方法 为了更好地理解 import collection mutable import java util
  • Function.call 方法作为回调[重复]

    这个问题在这里已经有答案了 如果我遗漏了什么 请原谅 但是当我尝试使用 call 方法作为回调时 它在 Chrome 和 Node js 中都会出现奇怪的错误 foo bar map String prototype trim call T
  • Rust 中的多种返回类型[重复]

    这个问题在这里已经有答案了 我有一个库函数f1 in rust返回一个字符串并想要更新它以选择性地返回一个向量 fn f1 gt String abc fn f2 gt String Vec
  • Hadoop kerberos 票证自动续订

    我在使用以下命令从 HDFS 下载大文件夹时遇到一些问题 hadoop fs get path to hdfs big folder 该文件夹很大 几乎 3TB kerberos 票证的生命周期为 10 小时 可续订生命周期为 7 天 下载
  • 如何将文件下载到 PHP 服务器?

    是否可以使用 PHP 脚本将远程服务器上的文件下载到我的 Web 服务器上 我有自己的网络服务器和域 我想在该域上放置一个 php 脚本 它将文件从远程服务器下载到我的服务器的文件系统上 这可能吗 Jim 当然 您需要文件系统上某处 您要保
  • 无法将图片从drawable发布到facebook

    我正在尝试将图像从可绘制文件夹传递到提要对话框 但我无法在 Facebook feed 对话中查看图像 其余参数可用 我正在使用 Facebook SDK 3 5 这是显示提要对话框的功能 private void publishFeedD
  • C++ - Qt - Visual Studio 2010 - 具有 GUI 和控制台的应用程序

    如果没有给程序提供任何参数 它将作为 GUI 应用程序启动 如果给定参数 它将通过命令行运行 我能够使用 Properties gt Linker gt SubSystem Console SUBSYSTEM CONSOLE 让 Visua
  • 添加一个新的可绘制对象,它正在更改解析的 xml 的图标

    我面临着一个只有在添加新的可绘制对象时才会发生的问题 我有一个已解析的xml to Fragment the icon设置为int 如果我添加新的可绘制对象 那么它会选择随机可绘制对象来显示已解析的图标xml 我有一个Adapter为了Re
  • 求 cos 的倒数

    at http www teacherschoice com au Maths Library Trigonometry solve trig SSS htm有 使用科学计算器求出 0 25 的反余弦 C cos 1 0 25 104 47
  • Laravel - 调用未定义的方法 Illuminate\Foundation\Application::share()

    我正在从 Laravel 5 3 升级到 Laravel 5 4 问题是当我跑步时composer update当谈到php artisan optimize部分 我收到错误 Symfony Component Debug Exceptio
  • 如何唤醒休眠线程并退出主线程?

    我正在创建 10 个线程 每个线程都会执行一些任务 有 7 项任务需要完成 由于任务数量小于线程数量 因此总会有 3 个线程处于休眠状态且不执行任何操作 我的主线程必须等待任务完成 只有当所有任务完成时 即线程退出时 才退出 我正在 for
  • 更改 tomcat 上 spring mvc 应用程序的应用程序根目录

    我正在 Spring MVC 3 0 上使用示例 RESTEasy 2 0 资源并部署到 Tomcat 6 我可以通过 http localhost 8080 examples resteasy 2 1 SNAPSHOT contacts
  • 使用 python 打印 Excel 工作簿

    假设我有一个excel文件excel file xlsx我想使用 Python 将其发送到我的打印机 所以我使用 import os os startfile path to file print 我的问题是 这仅打印 Excel 工作簿的
  • 如何搜索并替换内部包含等号“=”的字符串

    我必须从像 Pippo K 5 这样的 txt 中搜索字符串并将其替换为 Pippo K 1 我需要搜索整个字符串 我所做的是 set search Pippo K 5 set replace Pippo K 1 set textFile
  • 连接不同数据库中的多个表?数据库

    嘿 我正在寻找一种好方法 使用 php 连接到 mysql 中的至少 2 个数据库 并从表中收集每个数据库中的信息 这些表格将包含相关信息 例如 我在一个名为 sites 的表中的一个数据库 siteinfo 中有站点名称 我还在另一个数据
  • 如何更改数据透视表,使其以所需的方式显示数据?

    我已经能够将数据透视表拖到舞池上 但无法让它趴下来 似乎我们一直踩到对方的脚趾 我已经在工作表上获得了用于构建数据透视表的数据 此类描述了该数据 public class PriceVarianceData public String Un
  • Mac OS 上 Valgrind 下的 std::thread.join() SIGSEGV

    以下简单代码 C 11 将在 Mac OS 和 Linux 上运行 include
  • 位图 - 内存不足异常

    当我尝试从相机或图库获取图像时 出现错误 这是 logcat 的一部分 06 27 05 51 47 297 E dalvikvm heap 438 Out of memory on a 35295376 byte allocation 0
  • 将 JavaMail 与 Google AppEngine 一起使用时出现异常:如何解决此问题?

    我正在尝试使用 JavaMail 编写一个 Java 程序在 2 个用户之间发送电子邮件 我还没有将mail jar 和activation jar 文件添加到我的appengine 项目中 因为我在某处读到这会导致抛出异常 因为appen
  • 如何解决 Rust 中可变引用的生命周期错误?

    我不确定为什么以下代码无法编译 use std cmp Ordering struct MyItr lt a gt cur a i32 impl lt a gt Ord for MyItr lt a gt fn cmp self other