这是对我之前问题的跟进:如何创建和使用回调函数列表。
我正在尝试创建(并在事件循环附近存储)一个回调函数列表,在将来某个不确定的时间点调用它们。
我正在尝试创建(并在事件循环附近存储)一个回调函数列表,在将来某个不确定的时间点调用它们。
struct ComplexThing {
calls: Vec<Box<FnMut()>>,
}
impl ComplexThing {
fn call<'a, T: FnMut() + 'a>(&'a mut self, func: T) {
self.calls.push(Box::new(func));
}
}
出现错误:
calls.rs:30:25: 30:39 error: the parameter type `T` may not live long enough [E0310]
calls.rs:30 self.calls.push(Box::new(func));
^~~~~~~~~~~~~~
calls.rs:30:39: 30:39 help: consider adding an explicit lifetime bound `T: 'static`...
calls.rs:30:25: 30:39 note: ...so that the type `T` will meet its required lifetime bounds
calls.rs:30 self.calls.push(Box::new(func));
^~~~~~~~~~~~~~
我尝试将其添加到struct
中,这样就可以解决对push
调用的生命周期错误了。
struct ComplexThing<'a> {
calls: Vec<Box<FnMut() + 'a>>,
}
impl ComplexThing {
fn call<'a, T: FnMut() + 'a>(&'a mut self, func: T) {
self.calls.push(Box::new(func));
}
}
...但是给我的结果是:
calls.rs:28:6: 28:18 error: wrong number of lifetime parameters: expected 1, found 0 [E0107]
calls.rs:28 impl ComplexThing {
^~~~~~~~~~~~
是的,我想结构体有一个 <'a>
,但我没有指定它。如果我添加它,
impl ComplexThing<'a> {
我明白了,
calls.rs:28:19: 28:21 error: use of undeclared lifetime name `'a` [E0261]
calls.rs:28 impl ComplexThing<'a> {
我不确定是否应该在 struct ComplexThing
上指定它。如果我去掉它(我非常希望这样做,我想),
我认为Rust对生命周期的符号表示中有一些至关重要的东西我没有理解。 ComplexThing
(目前) 尝试存储在一个 Box
中的 FnMut
是由 ComplexThing
的实例所拥有的; 它的生命周期应该比 .ComplexThing
的生命周期短 - 即两件事情中的一件会发生:
ComplexThing
的一个私有函数将删除Vec
中的Box<FnMut>
(因此获得所有权),运行FnMut
,然后退出,因此释放FnMut
。ComplexThing
被释放,在这种情况下,Vec
和任何Box<FnMut>
也将被释放。
这个问题的"答案"让我想到Box<FnMut>
不需要生命周期注释,但是我在如何创建和使用回调列表中得到的答案让我认为我需要。
我的猜测是Box
只是存储一个指向我并不真正拥有的对象的指针,我需要在堆上创建FnMut
的副本或者将其移动构造到堆上,然后我才能拥有那个副本。(否则,如果它像在栈上的闭包一样,我需要确保在我的Box
之前,闭包不会超出作用域,这就是为什么Rust要求我注释生命周期的原因。)
Box<Trait>
是Box<Trait + 'static>
的语法糖,这完全解释了第一个错误。顺便说一下,&'a Trait
是&'a (Trait + 'a)
的语法糖。 - Chris Morgan