代码之家  ›  专栏  ›  技术社区  ›  Marco Bonelli

我的变量的生存期是否由于添加了一条显然不相关的指令而发生变化?

  •  3
  • Marco Bonelli  · 技术社区  · 7 年前

    我对生锈很陌生,还在读书 the book

    今天我试着写一个建议作为练习的程序(更准确地说是最后一个在 the end of chapter 8.3 ). 由于我仍在学习,因此速度很慢,我运行了一个新的 cargo build 对于我添加到 main.rs

    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
    

    cmd loop ,没关系,但是 main ? 任何与 命令

    为了找出问题所在,我删除了 match 手臂 Command::Add {...}

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

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

    我以为这两条线 与我的 命令

    1 回复  |  直到 6 年前
        1
  •  4
  •   Shepmaster Tim Diekmann    7 年前

    是的,我放弃了 cmd 在循环结束时,没关系

    String 在回路内部, 然后做一个 Command 从它。 命令 只是说它包含引用,在同一个生命周期内。然后,代码将其中一个引用从 命令 HashMap

    循环退出后 哈希图 将包含对现在已解除分配的

    任何与 命令 在循环内发生

    不,没有。您将引用传递给 到函数。在这一点上,所有的赌注都结束了。这个函数可以做到 签字允许,包括:

    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);
    }