gpt4 book ai didi

rust - 为什么 unwrap_or() 在范围内保持借用?

转载 作者:行者123 更新时间:2023-11-29 07:50:21 26 4
gpt4 key购买 nike

尝试编译:

fn main() {
let mut vec = vec![1, 2, 3];
let four: &mut u32 = borrow_or_add(&mut vec, 4);
}

fn borrow_or_add(vec: &mut Vec<u32>, val: u32) -> &mut u32 {
vec.iter_mut().find(|v| **v == val).unwrap_or({
vec.push(val);

vec.last_mut().unwrap()
})
}

Playground

...给出以下结果:

q.rs:8:9: 8:12 error: cannot borrow `*vec` as mutable more than once at a time
q.rs:8 vec.push(val);
^~~
q.rs:7:5: 7:8 note: previous borrow of `*vec` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*vec` until the borrow ends
q.rs:7 vec.iter_mut().find(|v| **v == val).unwrap_or({
^~~
q.rs:12:2: 12:2 note: previous borrow ends here
q.rs:6 fn borrow_or_add(vec: &mut Vec<u32>, val: u32) -> &mut u32 {
...
q.rs:12 }
^
q.rs:10:9: 10:12 error: cannot borrow `*vec` as mutable more than once at a time
q.rs:10 vec.last_mut().unwrap()
^~~
q.rs:7:5: 7:8 note: previous borrow of `*vec` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*vec` until the borrow ends
q.rs:7 vec.iter_mut().find(|v| **v == val).unwrap_or({
^~~
q.rs:12:2: 12:2 note: previous borrow ends here
q.rs:6 fn borrow_or_add(vec: &mut Vec<u32>, val: u32) -> &mut u32 {
...
q.rs:12 }
^
q.rs:10:9: 10:12 error: cannot borrow `*vec` as mutable more than once at a time
q.rs:10 vec.last_mut().unwrap()
^~~
q.rs:7:5: 7:8 note: previous borrow of `*vec` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*vec` until the borrow ends
q.rs:7 vec.iter_mut().find(|v| **v == val).unwrap_or({
^~~
q.rs:12:2: 12:2 note: previous borrow ends here
q.rs:6 fn borrow_or_add(vec: &mut Vec<u32>, val: u32) -> &mut u32 {
...
q.rs:12 }
^

据我所知,unwrap_or() 的主体不能引用提到的 vec 的借用,那么为什么它没有从作用域中删除?有没有一种优雅的方式来实现这个功能?实际上,如果不使用两次传递和一个 bool(即 contains()),我找不到成功执行此操作的方法。

最佳答案

借用至少对整个语句有效。不幸的是,将 Option 拉出到单独的语句中的通常解决方案无济于事,因为它仍然包含一个可变引用(在 Some 中),它强制借用向量也被扩展。这在使用 find() 时似乎是不可避免的。编译器担心指向 Vector 存储的指针在某处 float ,并且可能会因插入 vector 而无效(这可能导致重新分配)。这不仅包括返回的 Option 中的指针,还包括可以由其中一个函数在内部创建的指针。如果不是因为没有“隐藏”指针并且您仅在 Option 不是 指针时按下,这将是一个非常合理的问题。生命周期系统的粒度不够细,无法捕捉到这一事实,而且我看不到修复或变通的简单方法。

你可以做的是使用 position 找到一个索引:

fn borrow_or_add(vec: &mut Vec<u32>, val: u32) -> &mut u32 {
match vec.iter().position(|&v| v == val) {
Some(i) => &mut vec[i],
None => {
vec.push(val);
vec.last_mut().unwrap()
}
}
}

请注意,向量中的索引本质上是美化的指针。如果向量发生变化,它们可能会开始引用错误的元素,尽管它们不会在重新分配时悬空,无效索引(大于最大有效索引)将导致 panic 而不是内存不安全。不过,从 position 获取索引然后用它建立索引只是正确的,因为向量在这两者之间没有(实质上)修改。

关于rust - 为什么 unwrap_or() 在范围内保持借用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30087338/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com