关于Rust HashMap和字符串借用的混淆
此程序接受整数N,后跟N行,其中包含两个由空格分隔的字符串。我想使用第一个字符串作为键,第二个字符串作为值,将这些行放入关于Rust HashMap和字符串借用的混淆,hashmap,rust,borrowing,Hashmap,Rust,Borrowing,此程序接受整数N,后跟N行,其中包含两个由空格分隔的字符串。我想使用第一个字符串作为键,第二个字符串作为值,将这些行放入HashMap: 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
HashMap
:
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]);
}
}
当我尝试将那些解析的字符串放入HashMap
并取消map.insert(数据[0],数据[1])的注释时代码>,编译失败,出现以下错误:
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() {
...
}
^
错误:无法将'input'作为可变项借用,因为它也是作为不可变项借用的[E0502]
input.clear();
^~~~~
注:“input”之前的借用发生在此处;不可变借用阻止“input”的后续移动或可变借用,直到借用结束
让data=input.split_whitespace().collect::();
^~~~~
注:以前的借阅到此结束
fn main(){
...
}
^
我不明白为什么会出现这个错误,因为我认为map.insert()
表达式根本没有借用字符串input
。split\u whitespace()
不会给您两个新的字符串包含输入的非空白部分(副本)。相反,您会在由input
管理的内存中获得两个&str
类型的引用。因此,当您尝试清除input
并将下一行输入读入时,您将尝试覆盖哈希映射仍在使用的内存
为什么split_whitespace
(以及我应该补充的许多其他字符串方法)通过返回&str
,使事情变得复杂?因为这已经足够了,在这种情况下,它可以避免不必要的拷贝。但是,在这种特定情况下,最好显式复制字符串的相关部分:
map.insert(data[0].clone(), data[1].clone());
谢谢你@delnan!你的回答确实澄清了我为什么会出错。但是map.insert(数据[0].clone(),数据[1].clone())代码>不起作用。通过更改let mut map=HashMap:::new(),我成功地绕过了错误
tolet mut-map=HashMap:::new()代码>并使用map.insert(数据[0]。到_-owned(),数据[1]。到_-owned())代码>。有没有更好的解决方案不需要分配额外的内存?@B.Wang哦,对不起,那是我的大脑放屁。不,没有好的方法可以避免分配额外的内存。基本上,需要有一个字符串来拥有&str
点所在的数据,并且它不能是输入
,因为该字符串会被重复覆盖。您可以将字符串
s放入一个单独的向量中(使用mem::replace
和一个空stirng),但这仍然需要分配向量。不过请注意,内存中不会有所有数据的两个副本,因为input
是循环使用的。
map.insert(data[0].clone(), data[1].clone());