闭包中引用的生命周期

2023-12-06

我需要一个闭包来引用其封闭环境中的对象的一部分。该对象是在环境中创建的,并且范围仅限于该环境,但一旦创建,它就可以安全地移动到闭包中。

用例是一个函数,它执行一些准备工作并返回一个将完成其余工作的闭包。这种设计的原因是执行限制:第一部分工作涉及分配,其余部分必须不进行分配。这是一个最小的例子:

fn stage_action() -> Box<Fn() -> ()> {
    // split a freshly allocated string into pieces
    let string = String::from("a:b:c");
    let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];

    // the returned closure refers to the subtrings vector of
    // slices without any further allocation or modification
    Box::new(move || {
        for sub in substrings.iter() {
            println!("{}", sub);
        }
    })
}

fn main() {
    let action = stage_action();
    // ...executed some time later:
    action();
}

这无法编译,正确说明&string[0..1]和其他人不能活得比string。但如果string搬进封闭区,就不会有问题了。有没有办法强制这种情况发生,或者有另一种方法允许闭包引用在其外部创建的对象的部分?

我也尝试过创建一个struct具有相同的功能来使移动完全明确,但是也不编译。再次,编译失败并出现以下错误&later[0..1]其他的仅存活到函数结束,但“借用的值必须在静态生命周期内有效”。

Even 完全避免了Box似乎没有帮助 - 编译器抱怨该对象的寿命不够长。


这里没有任何关于闭包的具体内容;它相当于:

fn main() {
    let string = String::from("a:b:c");
    let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];
    let string = string;
}

您正在尝试move the String同时还有未偿还的借款。在我的例子中,它是另一个变量;在您的示例中,它是闭包的环境。不管怎样,你仍然在移动它。

此外,您尝试将子字符串移动到与所属字符串相同的闭包环境中。这使得整个问题等同于为什么我不能在同一结构中存储值和对该值的引用?:

struct Environment<'a> {
    string: String,
    substrings: Vec<&'a str>,
}

fn thing<'a>() -> Environment<'a> {
    let string = String::from("a:b:c");
    let substrings = vec![&string[0..1], &string[2..3], &string[4..5]];
    Environment {
        string: string,
        substrings: substrings,
    }
}

该对象是在环境中创建的,并且其范围仅限于该环境

我不同意;string and substrings被创建outside关闭的环境和搬进了它。正是这个举动让你绊倒。

一旦创建,它就可以安全地移至闭包。

In this情况确实如此,但只是因为你,程序员,可以保证字符串数据的地址inside the String将保持不变。您知道这一点有两个原因:

  • String是通过堆分配在内部实现的,因此移动String不移动字符串数据。
  • The String永远不会被改变,这可能会导致字符串重新分配,从而使任何引用无效。

The easiest您的示例的解决方案是将切片简单地转换为Strings 并让闭包完全拥有它们。如果这意味着您可以释放一个大字符串以支持一些较小的字符串,那么这甚至可能是一个净收益。

否则,您符合“存在生命周期跟踪过于热心的特殊情况”中规定的标准为什么我不能在同一结构中存储值和对该值的引用?,所以你可以使用像这样的板条箱:

拥有_参考

use owning_ref::RcRef; // 0.4.1
use std::rc::Rc;

fn stage_action() -> impl Fn() {
    let string = RcRef::new(Rc::new(String::from("a:b:c")));

    let substrings = vec![
        string.clone().map(|s| &s[0..1]),
        string.clone().map(|s| &s[2..3]),
        string.clone().map(|s| &s[4..5]),
    ];

    move || {
        for sub in &substrings {
            println!("{}", &**sub);
        }
    }
}

fn main() {
    let action = stage_action();
    action();
}

衔尾蛇

use ouroboros::self_referencing; // 0.2.3

fn stage_action() -> impl Fn() {
    #[self_referencing]
    struct Thing {
        string: String,
        #[borrows(string)]
        substrings: Vec<&'this str>,
    }

    let thing = ThingBuilder {
        string: String::from("a:b:c"),
        substrings_builder: |s| vec![&s[0..1], &s[2..3], &s[4..5]],
    }
    .build();

    move || {
        thing.with_substrings(|substrings| {
            for sub in substrings {
                println!("{}", sub);
            }
        })
    }
}

fn main() {
    let action = stage_action();
    action();
}

请注意,我不是这两个箱子的专家用户,因此这些示例可能不是best使用它。

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

闭包中引用的生命周期 的相关文章

随机推荐

  • 使用 XCTestCase Objective-C 进行多重测试性能

    我在测试类中有2种性能测试方法 如果我单独运行它们 它们就会通过 如果我运行洞类方法 它们会失败并显示消息 由于未捕获的异常 NSInternalInconsistencyException 而终止应用程序 原因 API 违规 多次调用 X
  • 未应用 setPolyToPoly

    谁能帮我解决我遇到的图形问题 这段代码根本不应用 setPolyToPoly 它执行相机旋转 但不执行 polyToPoly 转换 我不明白为什么 final Camera camera mCamera final Matrix matri
  • 从对象数组中返回匹配的对象

    我想根据 searchString 从给定数组中搜索匹配的值对象 例如 搜索字符串为 Object 0 var objArray id 0 name Object 0 otherProp 321 secondVal stack id 1 n
  • 无法在 Spark 中配置 ORC 属性

    我正在使用 Spark 1 6 Cloudera 5 8 2 并尝试以下方法来配置 ORC 属性 但不影响输出 下面是我尝试过的代码片段 DataFrame dataframe hiveContext createDataFrame row
  • 如何使用实体框架代码优先迁移删除唯一索引

    我正在使用启用了 Code First 迁移的 Entity Framework 5 0 我使用以下方法添加了唯一键 CreateIndex dbo Groups Name true 现在我想使用下一个迁移的 Down 方法删除现有的唯一键
  • 从资产库 URL 获取 NSData

    我正在尝试从设备库的 mp4 文件获取 NSData 这个链接看起来像这样 assets library asset asset mp4 id 32515720 939A 456F 958F 0B2F397416EB ext mp4 我试过
  • JavaScript 按钮停止页面上的所有音频

    我正在使用 mixlr com 的嵌入播放器来播放音频 现在我需要一个按钮来停止整个网站的音频 尽管播放器有自己的播放暂停按钮 但我需要自己的按钮来控制整个网站的音频 如果我单击暂停按钮 它将暂停整个网站的音频 有人可以帮我吗 一键暂停所有
  • R 中多行的一次热编码

    假设我有以下格式的数据 ID VALUE a a a b d b d c 我想做的是对 ID 值进行一次热编码 当我使用model matrix 我得到 model matrix VALUE 1 df ID aVALUE bVALUE cV
  • 使用数据库优先方法时覆盖或替换默认构造函数

    我们使用数据库优先的方法来创建 MVC 模型 这意味着框架会在主模型中自动生成默认构造函数 cs文件 然而 我想设置几个默认值 问题是这个框架每次都会为此模型生成一个基本的 cs 文件 edmx已更新 有什么方法可以在部分类中重写此构造函数
  • 使用 Maven 构建 Groovy 项目时出现源错误

    我正在尝试使用 maven 构建我的第一个 groovy 项目 但我从 maven 收到以下错误 它是某种类型的源错误 但我不明白为什么我会收到它 INFO BUILD FAILURE INFO INFO Total time 3 186s
  • IntelliJ的Scala增量编译什么时候发生?

    IntelliJ的Scala增量编译什么时候发生 我注意到对文件进行更改不会导致相应的 class 文件 在 target 中 被更新 什么时候会发生这种情况 我认为你误解了 Scala 增量编译的工作原理 有两种不同的东西可以称为 Int
  • 访问VBA:查找列中的最大数字并加1

    在我的 Access 数据库中 我有一个名为 Demande 的表 我想读取 Numero de Commande 列中的所有记录并读取该列中最大的数字 以便我可以将该数字用于下一个新记录 这是我的桌子 关键索引是针对 Numero de
  • Windows Azure 与.NET 2.0 框架兼容吗?

    我有一个在 NET 2 0 框架中开发的服务 它安装在多个站点中并与我的应用程序一起使用 我希望该服务能够向我 报告 有关该应用程序的某些信息 我想看看 Windows Azure 是否可以让我将报告存储在云数据库中 并在需要时提取它们 我
  • 重写 WinForm ListView 控件上的 Drawitem 事件

    我希望 ListView 的所选项目在焦点丢失时保持清晰可见 在 Windows 7 上为暗灰色 我确实将 HideSelection 属性设置为 False 我想对列表视图执行某人对 TreeView 控件所做的操作 即重写 Drawno
  • Kubernetes 中具有子域重定向的通配符 SSL 证书

    我已将 Kubernetes 配置为使用 cert manager 和 LetsEncrypt 对我的所有应用程序使用一个通配符 SSL 证书 现在的问题是我无法配置子域重定向 因为 Ingress 有点 僵硬 以下是我试图实现这一目标的方
  • 将 char 存储到 int 变量中

    我正在学习 C 中的隐式转换 我读了下面的例子 char a std cin gt gt a I can enter an integer like 56 here std cout lt
  • 当我尝试使用最新的依赖项构建 Maven 空手道项目时出现编译错误

    I m new to Karate API automation tool and just try to set up the tool I m getting Compilation errors when I try to compi
  • 使用 setRepeating() 方法了解下一个闹钟时间

    我有时会在上午 9 00 下午 1 00 晚上 7 00 等时间设置 3 个待处理意图 这些意图每天使用 setRepeating 方法递归触发 这里我将所有这些待处理的意图唯一请求代码保存在本地 SQLite 数据库中 在这里 每当触发警
  • FFREE ST(i) 修改 x87 标记字中的哪些位?

    这个例子是用 NASM 编写的 section bss var28 resb 28 section text main Initialize finit fldpi Read Tag Word fstenv var28 mov ax var
  • 闭包中引用的生命周期

    我需要一个闭包来引用其封闭环境中的对象的一部分 该对象是在环境中创建的 并且范围仅限于该环境 但一旦创建 它就可以安全地移动到闭包中 用例是一个函数 它执行一些准备工作并返回一个将完成其余工作的闭包 这种设计的原因是执行限制 第一部分工作涉