我将闭包存储在如下结构中:
#[derive(Clone)]
struct S<'a> {
func: &'a FnOnce() -> u32
}
fn main() {
let s = S { func: &|| 0 };
let val = (s.func)();
println!("{}", val);
}
当我编译时,s.func
无法移动以执行自身。我理解为什么它不能被移动(即它只是一个引用,并且它的大小在编译时未知),但根本不知道为什么它被移动——仅仅是因为闭包是通过特征实现的吗?
这是错误消息:
error[E0161]: cannot move a value of type std::ops::FnOnce() -> u32:
the size of std::ops::FnOnce() -> u32 cannot be statically determined
--> main.rs:8:15
|
8 | let val = (s.func)();
| ^^^^^^^^
error[E0507]: cannot move out of borrowed content
--> main.rs:8:15
|
8 | let val = (s.func)();
| ^^^^^^^^ cannot move out of borrowed content
error: aborting due to 2 previous errors
这是解决这个问题的唯一方法吗?将闭包存储在堆上(通过Box<FnOnce() -> u32>
)?为什么调用闭包会移动它?据推测,调用它不会改变函数本身。
关闭地点正在移动,因为FnOnce::call_once https://doc.rust-lang.org/stable/std/ops/trait.FnOnce.html#tymethod.call_once takes self
按价值。该合约强制保证该函数不会被多次调用。
如果您确实最多调用一次闭包,并且您想使用FnOnce
特征,那么你的结构需要拥有该闭包的所有权(并且你需要使你的结构在闭包类型上通用)。请注意,调用闭包会将闭包移出结构,从而使整个结构无效;你可以通过包装来解决这个问题FnOnce
in an Option
and take https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.take- 关闭闭包Option
在调用它之前。
如果您可能多次调用闭包,您不想获得闭包的所有权,或者您不想使您的结构在闭包类型上通用,那么您应该使用Fn
or FnMut
反而。Fn::call https://doc.rust-lang.org/stable/std/ops/trait.Fn.html#tymethod.call takes self
通过参考和FnMut::call_mut https://doc.rust-lang.org/stable/std/ops/trait.FnMut.html#tymethod.call_mut takes self
通过可变引用。由于两者都接受引用,因此您可以将特征对象与它们一起使用。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)