无法将`*x`作为可变借用,因为它也被作为不可变借用。

5

我正在做一个组合优化项目,以学习Rust语言,但我遇到了自己无法解决的问题...

我有2个函数:

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
2个回答

6
你正在尝试做一些基本上不可能的事情。
当你调用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))>,你就不会遇到这个问题。或者修改代码,在调用get_pareto_front_offline后不要触碰neighborhood

谢谢!你的解决方案正是我所想的... 我正在尝试制作一个优化的解决方案来解决这个问题,但是由于我的 Rust 水平,这真的很难 :-/ - WebTogz
在这种情况下,您通常需要一个专门的集合。我相信 VecDeque 可以解决问题(但我可能错了)。https://doc.rust-lang.org/std/collections/struct.VecDeque.html或者,您可以使用通道 https://doc.rust-lang.org/std/sync/mpsc/ - nielsle

6
在这种情况下,编译器通过不接受代码帮助您避免了使用后释放错误。问题可以简化为以下代码段:
fn main() {
    let mut v = vec![0,1,2,3];
    let r = &v[2];
    v.push(5);
    println!("{}", *r); // oops
}

一个Vec有长度和容量。如果长度等于容量,意味着缓冲区没有足够的空间存储新元素。在这种情况下,push操作将涉及将所有元素移动到一个足够大的新缓冲区中以存储新数据。但是,此操作会使引用r无效,因为r仍然存储第三个向量元素的旧地址,现在已经无效了。这正是Rust试图通过借用规则和借用检查器防止的错误类型。
但是,如果您只是向向量中添加新内容,它不会更改已经存在的元素的顺序。也许您可以用索引替换一些对Vec元素的引用,这些索引不管Vec元素存储在哪里都保持不变。
一些附加建议:对于函数参数,请使用&[T]而不是&Vec<T>,这样更灵活。此外,pareto_front == vec![]可以替换为pareto_front.is_empty()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接