最近开始学习Rust,用HashMap写demo时,遇到一个奇怪的问题,想了好久都想不明白,请您指教:
原代码如下:
use std::collections::HashMap;
fn main() {
Solution::test();
Solution::length_of_longest_substring(String::from("adekaehgo"));
}
struct Solution {}
impl Solution {
pub fn length_of_longest_substring(s: String) -> i32 {
let mut start: usize = 0;
let mut end: usize = 0;
let mut len = 1;
let mut max_len = 1;
let mut map: HashMap<u8, usize> = HashMap::new();
let mut n: usize = 0;
let arr = s.as_bytes();
for e in arr {
match map.get(e) {
Some(v) => {
//repeat
println!(
"repeat chat = ({},{}),start at {}, end at = {}, len = {}",
e, v, start, end, len
);
start = *v + 1;
println!("start = {}", start);
end = n;
len = end - start;
map.insert(*e, n);
Solution::remove_before(arr, v, &mut map);
}
None => {
//not repeat
end += 1;
map.insert(*e, n);
len = end - start;
if len > max_len {
max_len = len;
}
}
}
n += 1;
}
return max_len as i32;
}
fn remove_before(arr: &[u8], i: &usize, hashmap: &mut HashMap<u8, usize>) {
let mut n = 0;
while n < *i {
let c = arr[n];
hashmap.remove(&c);
n += 1;
}
}
pub fn test() {
let mut map: HashMap<u8, usize> = HashMap::new();
let mut n = 0;
let arr = [3; 3];
for e in &arr {
map.insert(*e, 564);
map.insert(*e, 2);
match map.get(e) {
Some(a) => {
println!("{}", a);
//map.remove("tset");
map.insert(*e, 45);
Solution::remove_before(&arr, &2, &mut map)
}
None => (),
}
//map.insert(*e, 78);
n += 1;
}
}
}
其中length_of_longest_substring为我写的解决问题的函数,但是却一直编译报错如下:
error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable
--> src/main.rs:31:21
|
20 | match map.get(e) {
| --- immutable borrow occurs here
...
31 | map.insert(*e, n);
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
32 | Solution::remove_before(arr, v, &mut map);
| - immutable borrow later used here
无奈,我仿照这个函数写了一个test函数,核心代码与报错的函数逻辑相似,但是却可以编辑成功并执行,想了好久都不明白,请指教
1
共 11 条评论, 1 页
评论区
写评论let vv = *v; 这里是 vv用的copy 语义,产生了新的变量。 由于nll优化,变量v在此后不被使用,因此编译器判断其作用域提前结束。 后续可变引用可以允许执行。
这种地方可以考虑使用hashmap::entry更容易理解
对以下内容的回复:
嗯嗯,就像之前的前辈说的,Some(v)中的v实际上持有了map的引用,改变一下就好了
搞了个最小例子,跟lz的问题一样,方便研究
对以下内容的回复:
好的,明白了一些,非常感谢您的帮助
对以下内容的回复:
非常感谢您不辞辛苦的答复,看来我还要多加学习,理解语言的细节
对以下内容的回复:
好的,谢谢您的答复,我再研究研究
我觉得按照编译器给的提示理解就可以了。提示分3段:
map.get()
返回的Some(v)
有对map
的共享引用;map.insert()
需要一个对map
的独占引用;v
(对map
的共享引用),那么根据NLL(大概),编译器知道这两个不冲突,所以给过了;但是这里用了v
,那就得把对map
的共享引用保留到这时候,那就和上面的对map
的独占引用有冲突了。我理解大概就是这么个意思。
关键是
Solution::remove_before(arr, v, &mut map)
这里,v
包含了对map
的一个不可变引用,&mut map
又是对map
的一个可变引用,冲突了。改了版能用的,虽然还没研究明白
我也晕了,等一位大神 对以下内容的回复:
把test里的
改成
就一样的报错了