Confusion about Rust HashMap and String borrowing

好久不见. 提交于 2020-01-05 03:04:42

问题


This program accepts an integer N, followed by N lines containing two strings separated by a space. I want to put those lines into a HashMap using the first string as the key and the second string as the value:

use std::collections::HashMap;
use std::io;

fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input)
        .expect("unable to read line");
    let desc_num: u32 = match input.trim().parse() {
        Ok(num) => num,
        Err(_) => panic!("unable to parse")
    };

    let mut map = HashMap::<&str, &str>::new();
    for _ in 0..desc_num {
        input.clear();
        io::stdin().read_line(&mut input)
            .expect("unable to read line");
        let data = input.split_whitespace().collect::<Vec<&str>>();
        println!("{:?}", data);
        // map.insert(data[0], data[1]);
    }
}

The program works as intended:

3
a 1
["a", "1"]
b 2
["b", "2"]
c 3
["c", "3"]

When I try to put those parsed strings into a HashMap and uncomment map.insert(data[0], data[1]);, the compilation fails with this error:

error: cannot borrow `input` as mutable because it is also borrowed as immutable [E0502]
        input.clear();
        ^~~~~
note: previous borrow of `input` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `input` until the borrow ends
        let data = input.split_whitespace().collect::<Vec<&str>>();
                   ^~~~~
note: previous borrow ends here
fn main() {
...
}
^

I don't understand why this error would come up, since I think the map.insert() expression doesn't borrow the string input at all.


回答1:


split_whitespace() doesn't give you two new Strings containing (copies of) the non-whitespace parts of the input. Instead you get two references into the memory managed by input, of type &str. So when you then try to clear input and read the next line of input into it, you try overwriting memory that's still being used by the hash map.

Why does split_whitespace (and many other string methods, I should add) complicate matters by returning &str? Because it's often enough, and in those cases it avoid unnecessary copies. In this specific case however, it's probably best to explicitly copy the relevant parts of the string:

map.insert(data[0].clone(), data[1].clone());


来源:https://stackoverflow.com/questions/38008547/confusion-about-rust-hashmap-and-string-borrowing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!