Rust(+ SFML) - 如何在受生命周期参数限制时避免额外的对象构造?

时间:2014-06-26 03:57:52

标签: sfml rust lifetime lifetime-scoping

我现在使用rust-sfmlrsfml::graphics)向屏幕绘制像素。 (我只是从Rust和项目开始。)我将数据存储在Image中,然后复制到Texture

Texture用于创建Sprite<'s>;这是我的问题。我需要能够改变Texture,但Sprite<'s>的类型似乎可以保证我不能做我想做的事情。由于每次重绘窗口时我都需要能够调用window.draw(&sprite),因此我每次只创建一个新的Sprite

优选的替代方案是将Sprite<'s>struct Render一起保留在Texture中。因为&#39; Sprite&#39;有一个生命周期参数,它变为struct Render<'s>

struct Render<'s> {
    texture: Texture,
    sprite: Sprite<'s>,
}

我在Render上有一个方法:

fn blit(&'s mut self) -> ()

改变Render(通过编辑Texture)。现在,只要我尝试多次调用blit,我就遇到了这个问题:

render.blit();
render.blit();  // error: cannot borrow `render` as mutable more than once at a time
我认为,这是因为生命周期参数强制Render的生命周期借用 - blit - 调用等于Render实例的生命周期(整个主要功能)。

如何保留原始Sprite并继续改变容器?有可能吗?

这是一个看起来很愚蠢且相当简单的例子:

extern crate rsfml;

use rsfml::graphics::Sprite;

fn main() -> () {
    let mut render = Render::new();
    render.blit();
    render.blit();  // error: cannot borrow `render` as mutable more than once at a time
}

struct Render<'s> {
    sprite: Option<Sprite<'s>>,
}

impl<'s> Render<'s> {
    fn new() -> Render { Render { sprite: None } }
    fn blit(&'s mut self) -> () { }
}

(如果问题不明确,请道歉。当我对这些概念不太熟悉时,很难表达。)

1 个答案:

答案 0 :(得分:2)

当你致电blit时,有两个生命周期在考虑之中;你知道,self类型&'ρ₀ Render<'ρ₁>的某些寿命ρ0和ρ1。在你的impl<'s> Render<'s>声明中,你已经声明ρ1是's,并且在你的&'s mut self中你宣称ρ是's:因此,借用{的生命周期{ {1}} self ,这意味着您只能拥有一个借用,因为它将一直存在,直到类型的破坏 - 它被声明为“至少与被称为“。

的类型

您希望对此进行更改,以便为's函数引入 new 生命周期参数,该参数允许小于blit;你希望ρ0是最小的,只与返回值绑定(因为我认为你实际上正在使用's - 如果没有,你应该省略它并允许编译器推断我们将要显式写入的内容) 。这样,借用只会在函数的返回值仍然在范围内时才会激活(在你的例子中,它没有被使用,所以你可以立即采取另一个参考)。

然后,这是对需要完成的功能的改变:

's

如果您将此更改为具有返回值并使用它,则在再次调用fn blit<'a>(&'a mut self) { } 之前,您需要确保它超出范围。这可能意味着将其直接传递给一个函数,或者它可能意味着引入一个新的范围,如下所示:

blit