不能将`* x`借用为可变因为它也被借用为不可变的

时间:2015-11-29 16:23:04

标签: rust immutability mutable borrowing

我正在制作一个组合优化项目来学习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

2 个答案:

答案 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()