我正在制作一个组合优化项目来学习Rust,我遇到了一个我无法解决的问题...
我有两个功能:
pub fn get_pareto_front_offline<'a>(scheduling_jobs: &'a Vec<Vec<u32>>, costs_vector: &'a Vec<(u32, u32)>) -> Vec<(&'a Vec<u32>, &'a (u32, u32))> {
// ...
}
和
pub fn pareto_approach_offline<'a>(list_of_jobs: &'a mut Vec<Vec<u32>>, neighborhood: &'a mut Vec<Vec<u32>>, costs: &'a Vec<(u32, u32)>) -> Vec<(&'a Vec<u32>, &'a (u32, u32))> {
let pareto_front = get_pareto_front_offline(neighborhood, costs);
loop {
if pareto_front == vec![] {
break;
}
neighborhood.clear();
for front in pareto_front.iter() {
neighborhood.push((front.0).clone());
}
}
pareto_front
}
我遇到了问题,因为编译器告诉我:
cannot borrow '*neighborhood' as mutable because it is also borrowed as immutableat line 15 col 9
cannot borrow '*neighborhood' as mutable because it is also borrowed as immutableat line 19 col 13
答案 0 :(得分:5)
你正试图做一些根本不可能的事情。
当您致电get_pareto_front_offline
时,您会将neighborhood
重新借用到该功能中。必须维护此重新借用,以使pareto_front
保持有效。换句话说,只要存在pareto_front
,编译器将不允许您以任何方式访问neighborhood
。
这是一件好事,因为您继续尝试清除我们的neighborhood
,这几乎当然使pareto_front
无效,可能会导致免费使用并破坏你的程序状态。
目前尚不清楚你正在尝试做什么;但你不能这样做。
顺便说一句,即使它被编译,该循环可能永远不会完成运行:永远不会满足您的终止条件(pareto_front == vec![]
),因为您永远不会修改pareto_front
;它要么立即停止,要么永远运行。
摆脱借贷问题的最简单方法是复制事物,这样你就不需要长期借款;如果get_pareto_front_offline
返回了Vec<(Vec<u32>, (u32, u32))>
,则不会出现此问题。那,或者修改为代码,以便在您致电neighborhood
后触摸get_pareto_front_offline
。
答案 1 :(得分:2)
在这种情况下,编译器通过不接受代码来帮助您避免使用后释放错误。问题可以简化为这段代码:
fn main() {
let mut v = vec![0,1,2,3];
let r = &v[2];
v.push(5);
println!("{}", *r); // oops
}
Vec有长度和容量。如果length等于容量,则意味着缓冲区中没有剩余空间用于新元素。在这种情况下,push
涉及将所有元素移动到足以存储新数据的新缓冲区。但是此操作会使引用r
无效,因为r
仍然存储第3个向量元素的旧地址和现在无效的地址。这正是Rust试图通过借用规则和借用检查器来防止的错误。
但是如果你只是向向量中添加新东西,它将不会改变已经存在的元素的顺序。也许您可以用Vec元素替换一些引用,无论Vec元素存储在哪里,索引都保持不变。
有些建议:首先&[T]
优先于&Vec<T>
来获取函数参数。它更灵活。此外,pareto_front == vec![]
可以替换为pareto_front.is_empty()
。