为什么需要这个克隆?

我正在学习 Rust 并使用 Rust 和 Gtk 创建一个非常简单的应用程序:

extern crate gtk;

use gtk::prelude::*;
use gtk::{Window, WindowType, TextView, TextBuffer, timeout_add_seconds};

fn make_window() {
    let window = Window::new(WindowType::Toplevel);

    let textview = TextView::new();
    window.add(&textview);

    let buffer = match textview.get_buffer() {
        Some(x) => x,
        None => panic!("Textview did not contain a buffer."),
    };

    buffer.connect_changed(move |buffer: &TextBuffer| {
        let b = buffer.clone(); // Why is this clone needed?
        timeout_add_seconds(1, move || {
            let ref buffer = b;
            Continue(false)
        });
    });
    window.show_all();
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    make_window();
    gtk::main();
}

我很困惑为什么buffer.clone()在内部关闭之前需要这样做。

如果我忽略它,我会收到关于生命周期的错误。但据我所知,无论有没有克隆,两者都有相同的生命周期。那么为什么一个有效而一个无效呢?

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:18:17
   |
18 |         let b = buffer; // Why is this clone needed?
   |                 ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the body at 17:54...
  --> src/main.rs:17:55
   |
17 |       buffer.connect_changed(move |buffer: &TextBuffer| {
   |  _______________________________________________________^ starting here...
18 | |         let b = buffer; // Why is this clone needed?
19 | |         timeout_add_seconds(1, move || {
20 | |             let ref buffer = b;
21 | |             Continue(false)
22 | |         });
23 | |     });
   | |_____^ ...ending here
note: ...so that expression is assignable (expected &gtk::TextBuffer, found &gtk::TextBuffer)
  --> src/main.rs:18:17
   |
18 |         let b = buffer; // Why is this clone needed?
   |                 ^^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:19:32: 22:10 b:&gtk::TextBuffer]` will meet its required lifetime bounds
  --> src/main.rs:19:9
   |
19 |         timeout_add_seconds(1, move || {
   |         ^^^^^^^^^^^^^^^^^^^
卢卡斯·卡尔伯托特

但据我所知,无论有没有克隆,两者都有相同的生命周期。

这并不完全正确。如果你克隆一个变量,你现在有两个版本的变量。每个都可以由不同的所有者拥有,因此两者都可以有不同的生命周期。这正是你的情况发生的事情,它只是有点隐藏 - 感谢关闭魔法。

让我们再次查看您的代码(我更改了一些变量名称,以便稍后明确引用它们):

buffer_a.connect_changed(move |buffer_b: &TextBuffer| {
    let b = buffer_b.clone(); // Why is this clone needed?
    timeout_add_seconds(1, move || {
        let ref buffer_c = b;
        Continue(false)
    });
});

在这里,变量b是通过克隆创建的,并且首先存在于外部闭包中(它是那里的局部变量)。但随后它在作为闭包的内部闭包内使用move因此,b被移动所述内罩,然后拥有TextBuffer是:内部闭包拥有缓冲区b这意味着它的b生命周期与闭包一样长;独立于原来的一生!

为了确保我们理解所有内容,只需检查各种变量的类型:

  • buffer_a: 类型 TextBuffer
  • buffer_b: 类型&TextBuffer可能是从 借来的buffer_a
  • bTextBuffer再次输入(我们克隆了buffer_b,带有 的clone()签名clone(&T) -> T
  • buffer_c:&TextBuffer再次(借用b

let ref buffer = b;条线进一步迷惑了这一点写起来更惯用let buffer = &b;(两个版本都做同样的事情)。

如果我们不克隆,为什么 Rust 会抱怨?内部闭合需要(通过timeout_add_seconds())到 'static(更正式的:“满足'static要求),这意味着关闭不能引用任何不长生不老(。 'static),如果我们不这样做克隆,内罩会。buffer_a不会永远存在的参考

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

hamcrest core,为什么需要这个?

来自分类Dev

为什么这个clojure宏需要''〜?

来自分类Dev

为什么这个变量需要是静态的?

来自分类Dev

为什么这个bash习语需要评估?

来自分类Dev

为什么克隆包装器需要堆栈参数?

来自分类Dev

为什么这个多元函数需要类型注释?

来自分类Dev

为什么这个tensorflow循环需要这么多的内存?

来自分类Dev

为什么这个Forking示例不需要互斥锁?

来自分类Dev

CPS协程:为什么这个示例需要精疲力尽?

来自分类Dev

Angular:更新列表;为什么需要这个$ broadcast?

来自分类Dev

为什么这个 == 窗口?

来自分类Dev

为什么要克隆公共Git存储库需要机器的ssh密钥?

来自分类Dev

为什么我总是需要在Backbone中克隆模型属性?

来自分类Dev

无法克隆线程 - 为什么?

来自分类Dev

这个函数需要输出什么?

来自分类Dev

为什么这个bubbleSort方法不起作用?为什么需要另一个 for 循环?

来自分类Dev

为什么这个jquery插件不需要垫片即可工作?

来自分类Dev

为什么在这个Java通用子类中需要一个构造函数?

来自分类Dev

为什么在这个rails try代码块中需要问号?

来自分类Dev

为什么一个人需要这个lambda:Function(x)x

来自分类Dev

如果这个更简单,更快的算法可行,为什么我们需要Dijkstra算法?

来自分类Dev

为什么在这个新手示例中需要List.reduce?

来自分类Dev

为什么联想B520整体机箱上需要这个正方形?

来自分类Dev

Swift3:为什么这个简单的代码块需要很长时间才能编译

来自分类Dev

js - 高阶一元函数 - 为什么需要这个?

来自分类Dev

为什么我不需要 JSON.stringify() 这个帖子有效载荷?

来自分类Dev

为什么这个 Rust 类型别名需要生命周期参数?

来自分类Dev

express logger、morgan logger 等为什么我的服务器应用程序中需要这个?

来自分类Dev

为什么我需要初始化这个成员数组

Related 相关文章

  1. 1

    hamcrest core,为什么需要这个?

  2. 2

    为什么这个clojure宏需要''〜?

  3. 3

    为什么这个变量需要是静态的?

  4. 4

    为什么这个bash习语需要评估?

  5. 5

    为什么克隆包装器需要堆栈参数?

  6. 6

    为什么这个多元函数需要类型注释?

  7. 7

    为什么这个tensorflow循环需要这么多的内存?

  8. 8

    为什么这个Forking示例不需要互斥锁?

  9. 9

    CPS协程:为什么这个示例需要精疲力尽?

  10. 10

    Angular:更新列表;为什么需要这个$ broadcast?

  11. 11

    为什么这个 == 窗口?

  12. 12

    为什么要克隆公共Git存储库需要机器的ssh密钥?

  13. 13

    为什么我总是需要在Backbone中克隆模型属性?

  14. 14

    无法克隆线程 - 为什么?

  15. 15

    这个函数需要输出什么?

  16. 16

    为什么这个bubbleSort方法不起作用?为什么需要另一个 for 循环?

  17. 17

    为什么这个jquery插件不需要垫片即可工作?

  18. 18

    为什么在这个Java通用子类中需要一个构造函数?

  19. 19

    为什么在这个rails try代码块中需要问号?

  20. 20

    为什么一个人需要这个lambda:Function(x)x

  21. 21

    如果这个更简单,更快的算法可行,为什么我们需要Dijkstra算法?

  22. 22

    为什么在这个新手示例中需要List.reduce?

  23. 23

    为什么联想B520整体机箱上需要这个正方形?

  24. 24

    Swift3:为什么这个简单的代码块需要很长时间才能编译

  25. 25

    js - 高阶一元函数 - 为什么需要这个?

  26. 26

    为什么我不需要 JSON.stringify() 这个帖子有效载荷?

  27. 27

    为什么这个 Rust 类型别名需要生命周期参数?

  28. 28

    express logger、morgan logger 等为什么我的服务器应用程序中需要这个?

  29. 29

    为什么我需要初始化这个成员数组

热门标签

归档