rust - 为什么 `move`不将引用的数据与引用一起移动?

标签 rust

此代码无法编译...

fn main() {
    let data = "hi".to_string();
    let wrap = &data;
    std::thread::spawn(move || println!("{}", wrap));
}
...因为data不在生成的线程中:
error[E0597]: `data` does not live long enough
 --> src/main.rs:3:16
  |
3 |     let wrap = &data;
  |                ^^^^^ borrowed value does not live long enough
4 |     std::thread::spawn(move || println!("{}", wrap));
  |     ------------------------------------------------ argument requires that `data` is borrowed for `'static`
5 | }
  | - `data` dropped here while still borrowed
为什么Rust不像data那样移动wrap?有什么方法可以迫使datawrap一起移动?
我的真实代码看起来更像这样。我接受一条消息,对其进行解析,然后将其发送到线程进行处理。
struct Message {
    data: Vec<u8>,
}
let message = Message {
    data: "{\"name\":\"Rust\"}".to_string(),
};

#[derive(Deserialize)]
struct Parsed<'a> {
    name: &'a str,
}
let parsed: Parsed = serde_json::from_slice(&message.data).unwrap();

std::thread::Builder::new()
    .name(parsed.name) // note: need some of the parsed data prior to moving into the thread...so cannot solve with JSON parsing inside thread
    .spawn(move || println("{}", parsed.name));
我知道我可以将Parsed结构修改为使用String而不是&'a str,但是当编译器应该能够很好地移动data时,这会降低效率。

最佳答案

Why doesn't Rust move data like it does wrap


有几个原因-请选择:
  • 因为捕获了wrap而不是data,所以闭包移动了捕获的内容。
  • 因为data的移动将立即使wrap本身以及对data的其他引用(如果存在)无效。另外,封闭范围本身可能需要data才能进行进一步访问。
  • 因为那样,就不可能有一个闭包来通过移动捕获某些值,并通过引用捕获某些值。当前,您可以创建一个move闭包,但仍然可以选择通过创建显式引用并捕获该引用来捕获某些值。您建议的功能将使此操作变得不可能。
  • 关于rust - 为什么 `move`不将引用的数据与引用一起移动?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64338318/

    相关文章:

    ruby - 是否将字符串传回 FFI 模块中必要的调用代码以防止内存泄漏?

    rust - 为什么在 hyper 中匹配请求路径后没有任何反应?

    vector - 如何在 Rust 中将值推送到 2D Vec?

    pointers - 通过多个 "as"转换如何转换原始 str ?

    json - 有没有办法在不创建细粒度对象的情况下使用 Serde 反序列化任意 JSON?

    rust - 尝试实现借用一些数据并拥有其他数据的迭代器时出现编译错误

    rust - 为什么删除返回给我一个错误 : expected type `()` but found type

    rust - 呼唤写!在 rust 中输出包裹在 Ok() 中的字符串

    rust - 加载.env并使用辅助函数将其转换为一般结构

    rust - 为什么在特征中返回 `Self` 有效,但返回 `Option<Self>` 需要 `Sized` ?