我正在使用Rust开发一个玩具光线追踪器项目,但遇到了与生命周期相关的错误。我已将代码简化为以下自包含的失败案例:
struct Material {}
pub struct Sphere<'a> {
material: &'a Material,
}
pub trait AnySceneObject {}
impl<'a> AnySceneObject for Sphere<'a> {}
pub struct Scene {
objects: Vec<Box<AnySceneObject>>,
}
fn main() {
let material = Material {};
let boxed_sphere: Box<AnySceneObject> = Box::new(Sphere { material: &material });
Scene { objects: vec![boxed_sphere] };
}
哪个抱怨
error[E0597]: `material` does not live long enough
--> main.rs:17:74
|
17 | let boxed_sphere: Box<AnySceneObject> = Box::new(Sphere { material: &material });
| ^^^^^^^^ does not live long enough
18 | Scene { objects: vec![boxed_sphere] };
19 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
error: aborting due to previous error(s)
我希望使用traits来定义场景中的对象,但是我希望Scene
对象拥有它们。 我的当前理解是这意味着我需要Box
或等效物,因为特质对象大小未知。
我还想让对象共享对Material
的引用,因为它们不会有很多,尽管它们相对简单并且可以使用Copy
,但我不希望有成千上万个相同的副本(因此使用&'a Material
)。
我很困惑在这里传递&material
为什么有问题:由于值是最后一个先被删除,所以Scene
会首先被删除,允许boxed_sphere
被删除(因为它现在拥有一个拥有Box
的Vec
),然后可以删除material
,没有问题? 因为我将名为material
的值保留了整个函数范围,所以它似乎应该至少与函数中的另外两个值一样长寿。
另外有点令人困惑的是,注释掉Scene
的实例化可以解决问题,原因我不理解。
Box
是否添加了第二层间接性?(2)在您的第二个代码片段中,它可以工作是因为main
拥有单个sphere
句柄,但如果我动态生成一个Vec <&AnySceneObject>
(比如从文件),某些东西需要拥有这些对象(对吧?),因此我使用了Box
(我意识到这在我的简化示例中被省略了)。 (3)推断的'static
来自哪里?这是因为它在main
中吗?(4)在这种情况下,枚举听起来更好。我在哪里可以阅读有关它们与引用在此上下文中的比较的信息? - skelley