提问人:wcy 提问时间:2/16/2022 更新时间:2/16/2022 访问量:1412
在没有引用返回值的情况下,一次不能多次借用“b”作为可变的 [duplicate]
Cannot borrow `b` as mutable more than once at a time without reference return value [duplicate]
问:
下面的 rust 代码有编译错误。
struct Builder;
impl Builder {
pub fn add(&mut self, id: i32) -> i32 {
id + 1
}
}
fn main() {
let mut b = Builder;
b.add(b.add(10));
}
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> examples/mutable_borrow_at_a_time.rs:10:11
|
10 | b.add(b.add(10));
| - --- ^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
与问题不同,一次不能多次借用“x”作为可变的,根本不返回任何引用。add
与问题“多次借入的借入错误”不同,返回类型是具有生存期的返回类型。i32
'static
而以下代码可以编译而不会出错。
struct Builder;
impl Builder {
pub fn add(&mut self, id: i32) -> i32 {
id + 1
}
}
fn main() {
let mut b = Builder;
let x = b.add(10);
b.add(x);
}
无论如何,每次为复合表达式创建一个虚拟变量都很麻烦。x
答:
1赞
at54321
2/16/2022
#1
首先,在外部会有一个可变的借用,然后会尝试在内部进行第二个可变的借用。编译器在您粘贴的错误消息中对此进行了精彩的解释和可视化:b.add(...)
b.add()
| b.add(b.add(10));
| - --- ^ second mutable borrow occurs here
| | |
| | first borrow later used by call
| first mutable borrow occurs here
此限制可能会在某个时候删除,但就目前而言,这就是它的工作原理。
对于您的特定示例,正如 Jmb 所提到的,您根本不需要,因此这将正常工作:mut
struct Builder;
impl Builder {
pub fn add(&self, id: i32) -> i32 {
id + 1
}
}
fn main() {
let b = Builder;
b.add(b.add(10));
}
1赞
prog-fh
2/16/2022
#2
看起来您正在尝试使用构建器模式。
困难在于将构建器从一个呼叫传递到另一个呼叫。
链中的每个步骤都应该消耗构建器的先前状态并发出一个新状态(如下所示)。
最后,最后一步 () 最后一次使用构建器,并发出我们打算构建的值。&mut
add()
build()
您可能会担心这些多个移动/使用操作的性能成本(而不是通过 更改),但是在启用优化时,编译器能够查看这些调用,并可以决定执行所有操作:一个仅包含 produce 的函数。&mut
Builder::new().add(10).add(20).build()
mov eax, 30 ret
struct Builder {
id: i32,
}
impl Builder {
pub fn new() -> Self {
Builder { id: 0 }
}
pub fn add(
mut self,
incr: i32,
) -> Self {
self.id += incr;
self
}
pub fn build(self) -> i32 {
self.id
}
}
fn main() {
let id = Builder::new().add(10).add(20).build();
println!("id={:?}", id);
}
评论
self
mut
builder