我正在玩Rust中的新闭包,我遇到了一种情况,再次向我显示我还没有完全掌握所有权规则。
#![feature(unboxed_closures)]
#![feature(overloaded_calls)]
fn main() {
let mut test = 5i;
let do_something = ref |:| { println!("{}", test) };
test = 6i;
do_something();
println!("{}", test);
}
此代码无法告诉我作业test = 6i;
无效,因为test
已经借用do_something
封闭。
但是阅读所有权规则(来自Rust指南)对我来说似乎有用:
1.您可以控制何时释放该资源。
2.您可以不可避免地将该资源借给任意数量的借款人。
3.您可以将资源可变地借给一个借款人。 BUT
4.一旦你这样做了,你可能也不会以其他方式,可变或不可变的方式借出来。
5.如果你现在把它借给某人,你可能不会透支出来。
上面的代码有什么问题。 test
是所有者,do_something
应该只有不可变引用。如果我们借给某人的唯一引用是 immutable ,那么更改test
的值是不合法的呢?
关注
现在我了解到所有者的访问权限也被视为贷款,我将代码更改为使用Cell
。
#![feature(unboxed_closures)]
#![feature(overloaded_calls)]
use std::cell::Cell;
fn main() {
let test = Cell::new(5i);
let do_something = ref |:| { println!("{}", test) };
test.set(6i);
do_something();
println!("{}", test);
}
但我想知道为什么这会打印
5
6
而不是
6
6
我如何更改代码才能打印出来?
6
6
答案 0 :(得分:2)
正如你引用自己:
如果您目前正在将其借给某人,您可能不会透支出来。
由于您已将test
借给do_something
,因此在do_something
超出范围之前,您无法以可变方式访问它。
答案 1 :(得分:2)
回答你的后续行动:
这似乎是因为Cell
是Copy
,所以它被复制到闭包中。如果你这样做(现在ref
在关闭之前无关紧要并且可以省略):
#![feature(unboxed_closures)]
#![feature(overloaded_calls)]
use std::cell::Cell;
fn main() {
let test = Cell::new(5i);
let test_ref = &test;
let do_something = |:| { println!("{}", test_ref.get()) };
test.set(6i);
do_something();
println!("{}", test.get());
}
然后打印两个6
s。
但是,我认为这种行为有些出乎意料。我当然希望带有ref
前缀的闭包会通过引用将所有的环境带入其中。我刚刚为此提交了issue。