gpt4 book ai didi

rust - 我的变量的生命周期是否由于添加了一个明显无关的指令而改变了?

转载 作者:行者123 更新时间:2023-11-29 07:58:43 25 4
gpt4 key购买 nike

我对 Rust 很陌生,还在阅读 the book时不时地编写一些简单的程序来测试我正在学习的内容。

今天我尝试编写一个建议作为练习的程序(更准确地说是 the end of chapter 8.3 上的最后一个)。由于我仍在学习,因此速度很慢,所以我为添加到我的 main.rs 中的几乎所有新行运行一个新的 cargo build。截至目前,它看起来像这样:

use std::io::{self, Write};
use std::collections::{HashMap, HashSet};

enum Command<'a> {
Add {name: &'a str, unit: &'a str},
List {unit: &'a str},
Exit
}

fn main() {
let mut units: HashMap<&str, HashSet<&str>> = HashMap::new();

loop {
let mut cmd = String::new();
io::stdin().read_line(&mut cmd).unwrap();

let cmd = match parse_command(&cmd) {
Ok(command) => command,
Err(error) => {
println!("Error: {}!", error);
continue;
}
};

match cmd {
Command::Add {name: new_name, unit: new_unit} => {
let mut u = units.entry("unit1").or_insert(HashSet::new());
u.insert(new_name);
},

Command::List {unit: target_unit} => {},
Command::Exit => break
}
} // end of loop
} // end of main

fn parse_command<'a>(line: &'a String) -> Result<Command<'a>, &'a str> {
Ok(Command::Exit)
// ... still need to write something useful ...
}

没什么复杂的,因为我什至还没有在我的 parse_command 函数中写任何东西,它目前只返回一个 Result::Ok(Command::Exit) ,但是当我尝试编译上面的代码时,出现以下错误:

error[E0597]: `cmd` does not live long enough
--> src/main.rs:34:2
|
17 | let cmd = match parse_command(&cmd) {
| --- borrow occurs here
...
34 | } // end of loop
| ^ `cmd` dropped here while still borrowed
35 | } // end of main
| - borrowed value needs to live until here

弄清楚应该没什么奇怪的,但我对这个错误很困惑。是的,我在 loop 的末尾放置了 cmd,这没问题,但是为什么借来的值需要一直存在到 main 结束?cmd 相关的任何事情都发生在 loop 中,为什么借用的值预期会比这更长寿?

为了找出问题所在,我删除了 Command::Add {...}match 臂内的两行,所以它看起来像这样:

    match cmd {
Command::Add {name: new_name, unit: new_unit} => {},
Command::List {unit: target_unit} => {},
Command::Exit => break
}

而且,令我惊讶的是,代码编译没有错误(尽管我需要这些行,所以这只是一个愚蠢的测试)。

我认为这两行与我的 cmd 变量没有关系,是吗?这是怎么回事?我 99% 确定我遗漏了一些非常愚蠢的东西,但我自己无法弄清楚它可能是什么。非常感谢任何帮助!

最佳答案

Yes, I drop cmd at the end of the loop, and that's ok

不,不是,这就是编译器告诉你的。 Rust 已经完成了它的工作,并阻止您将内存不安全插入到您的程序中。

您在循环内分配一个 String引用它 并从中创建一个 CommandCommand 只说明它包含引用,所有引用都具有相同的生命周期。然后代码从 Command 中取回这些引用之一,并尝试将其存储在 HashMap 中。

循环退出后,HashMap 将包含对现在已解除分配的 String 的引用,这将是一件非常糟糕的事情。

Anything related to cmd happens inside the loop

不,它没有。您将对 String 的引用传递给一个函数。到那时,所有的赌注都落空了。该函数可以执行签名允许的任何操作,包括:

fn parse_command<'a>(line: &'a String) -> Result<Command<'a>, &'a str> {
Ok(Command::Add {
name: line,
unit: line,
})
}

你的代码等同于:

use std::collections::HashSet;

fn main() {
let mut units = HashSet::new();

{
let cmd = String::new();
units.insert(&cmd);
}

println!("{:?}", units);
}

关于rust - 我的变量的生命周期是否由于添加了一个明显无关的指令而改变了?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45446237/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com