问题
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 String
s 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