为什么我不能连续两次调用可变方法(并存储结果)?
Why can't I call a mutable method (and store the result) twice in a row?
在下面的例子中:
struct SimpleMemoryBank {
vec: Vec<Box<i32>>,
}
impl SimpleMemoryBank {
fn new() -> SimpleMemoryBank {
SimpleMemoryBank{ vec: Vec::new() }
}
fn add(&mut self, value: i32) -> &mut i32 {
self.vec.push(Box::new(value));
let last = self.vec.len() - 1;
&mut *self.vec[last]
}
}
fn main() {
let mut foo = SimpleMemoryBank::new();
// Works okay
foo.add(1);
foo.add(2);
// Doesn't work: "cannot borrow `foo` as mutable more than once at a time"
let one = foo.add(1);
let two = foo.add(2);
}
add()
可以连续调用多次,只要我不存储函数调用的结果即可。但是如果我存储函数的结果(let one = ...
),我就会得到错误:
problem.rs:26:15: 26:18 error: cannot borrow `foo` as mutable more than once at a time
problem.rs:26 let two = foo.add(2);
^~~
problem.rs:25:15: 25:18 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends
problem.rs:25 let one = foo.add(1);
^~~
problem.rs:27:2: 27:2 note: previous borrow ends here
problem.rs:17 fn main() {
...
problem.rs:27 }
^
error: aborting due to previous error
这是issue #6393: borrow scopes should not always be lexical的表现吗?
我该如何解决这个问题?本质上,我想向向量添加一个新的 Box
,然后 return 对其的引用(以便调用者可以使用它)。
这正是 Rust 旨在防止您造成的问题。如果你这样做会发生什么:
let one = foo.add(1);
foo.vec.clear();
println!("{}", one);
或者如果 foo.add
通过在向量的 beginning 处推送新值来工作怎么办?会发生不好的事情!最主要的是,当你借用一个变量时,你不能再改变这个变量。如果你能够改变它,那么你可能会使借用的内存无效,然后你的程序可以做很多事情,最好的情况就是它崩溃。
Is this a manifestation of issue #6393: borrow scopes should not always be lexical?
有点,但不是真的。在此示例中,您从不使用 one
或 two
,因此理论上非词法范围将允许它编译。但是,您随后声明
I want to add a new Box to the vector, and then return a reference to it (so the caller can use it)
这意味着您的真实代码想要成为
let one = foo.add(1);
let two = foo.add(2);
do_something(one);
do_something(two);
所以变量的生命周期会重叠。
在这种情况下,如果您只是想要一个地方来存储不能单独释放的变量,不要彼此重叠,也不能移动,请尝试使用 TypedArena
:
extern crate arena;
use arena::TypedArena;
fn main() {
let arena = TypedArena::new();
let one = arena.alloc(1);
let two = arena.alloc(2);
*one = 3;
println!("{}, {}", one, two);
}
在下面的例子中:
struct SimpleMemoryBank {
vec: Vec<Box<i32>>,
}
impl SimpleMemoryBank {
fn new() -> SimpleMemoryBank {
SimpleMemoryBank{ vec: Vec::new() }
}
fn add(&mut self, value: i32) -> &mut i32 {
self.vec.push(Box::new(value));
let last = self.vec.len() - 1;
&mut *self.vec[last]
}
}
fn main() {
let mut foo = SimpleMemoryBank::new();
// Works okay
foo.add(1);
foo.add(2);
// Doesn't work: "cannot borrow `foo` as mutable more than once at a time"
let one = foo.add(1);
let two = foo.add(2);
}
add()
可以连续调用多次,只要我不存储函数调用的结果即可。但是如果我存储函数的结果(let one = ...
),我就会得到错误:
problem.rs:26:15: 26:18 error: cannot borrow `foo` as mutable more than once at a time
problem.rs:26 let two = foo.add(2);
^~~
problem.rs:25:15: 25:18 note: previous borrow of `foo` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `foo` until the borrow ends
problem.rs:25 let one = foo.add(1);
^~~
problem.rs:27:2: 27:2 note: previous borrow ends here
problem.rs:17 fn main() {
...
problem.rs:27 }
^
error: aborting due to previous error
这是issue #6393: borrow scopes should not always be lexical的表现吗?
我该如何解决这个问题?本质上,我想向向量添加一个新的 Box
,然后 return 对其的引用(以便调用者可以使用它)。
这正是 Rust 旨在防止您造成的问题。如果你这样做会发生什么:
let one = foo.add(1);
foo.vec.clear();
println!("{}", one);
或者如果 foo.add
通过在向量的 beginning 处推送新值来工作怎么办?会发生不好的事情!最主要的是,当你借用一个变量时,你不能再改变这个变量。如果你能够改变它,那么你可能会使借用的内存无效,然后你的程序可以做很多事情,最好的情况就是它崩溃。
Is this a manifestation of issue #6393: borrow scopes should not always be lexical?
有点,但不是真的。在此示例中,您从不使用 one
或 two
,因此理论上非词法范围将允许它编译。但是,您随后声明
I want to add a new Box to the vector, and then return a reference to it (so the caller can use it)
这意味着您的真实代码想要成为
let one = foo.add(1);
let two = foo.add(2);
do_something(one);
do_something(two);
所以变量的生命周期会重叠。
在这种情况下,如果您只是想要一个地方来存储不能单独释放的变量,不要彼此重叠,也不能移动,请尝试使用 TypedArena
:
extern crate arena;
use arena::TypedArena;
fn main() {
let arena = TypedArena::new();
let one = arena.alloc(1);
let two = arena.alloc(2);
*one = 3;
println!("{}, {}", one, two);
}