【发布时间】:2018-10-06 20:08:04
【问题描述】:
我有一个特征,它带有一个引用迭代器的函数:
#[derive(Clone)]
struct Dog {
name: &'static str,
}
trait DogListAction<'a, I>
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I);
}
struct DogListActionExample {}
impl<'a, I> DogListAction<'a, I> for DogListActionExample
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I) {
for dog in dog_list {
println!("{}", dog.name);
}
}
}
fn main() {
let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
let mut action_example = DogListActionExample {};
let mut dog_list_actions: Vec<Box<DogListAction<_>>> = vec![Box::new(action_example)];
loop {
let dog_clone = dogs.clone();
for dog_list_action in &mut dog_list_actions {
dog_list_action.on_dog_list(dog_clone.iter());
}
}
}
它没有对元素的任何引用,所以它没有必要比函数调用持续更多的时间。
由于我对生命的理解有限,我还不知道如何表达这一点。调用此函数会导致编译错误:
error[E0597]: `dog_clone` does not live long enough
--> src/main.rs:33:41
|
33 | dog_list_action.on_dog_list(dog_clone.iter());
| ^^^^^^^^^ borrowed value does not live long enough
34 | }
35 | }
| - `dog_clone` dropped here while still borrowed
36 | }
| - borrowed value needs to live until here
我猜借用检查器认为dog_clone中的数据可能会在函数结束后被引用,但事实并非如此。
【问题讨论】:
-
能否请您提供minimal example to reproduce the problem,最好带有操场链接?我看不出你显示的代码有什么问题。 (有关更多信息,另请参阅Rust tag wiki。)
-
这里是操场上一个最小示例的链接:play.rust-lang.org/…
-
我仍然认为问题在于编译器认为即使在调用函数之后 DogListAction 可能会引用来自迭代器的数据。我正在尝试添加明确的生命周期规范,但到目前为止没有运气
-
@Clynamen,这里的主要问题是代码可以潜在地将对
dog_clone元素的短期引用保存在寿命较长的dog_list_actions元素中。 -
如果将
dog_clone.iter()替换为dogs.iter(),代码将编译。您需要对函数on_dog_list()进行签名,以表达您不保存迭代器产生的引用的意图。