【问题标题】:"borrowed value does not live long enough" when using the builder pattern使用构建器模式时“借来的价值不够长”
【发布时间】:2015-04-12 17:28:30
【问题描述】:

我有以下代码:

pub struct Canvas<'a> {
    width: isize,
    height: isize,
    color: Color,
    surface: Surface,
    texture: Texture,
    renderer: &'a Renderer,
}

impl<'a> Canvas<'a> {
    pub fn new(width: isize, height: isize, renderer: &'a Renderer) -> Canvas<'a> {
        let color = Color::RGB(0, 30, 0);
        let mut surface = core::create_surface(width, height);
        let texture = Canvas::gen_texture(&mut surface, width, height, color, renderer);
        Canvas {
            width: width,
            height: height,
            color: color,
            surface: surface,
            texture: texture,
            renderer: renderer,
        }
    }

    pub fn color(&mut self, color: Color) -> &mut Canvas<'a> {
        self.color = color;
        self.texture = Canvas::gen_texture(
            &mut self.surface,
            self.width,
            self.height,
            self.color,
            self.renderer,
        );
        self
    }
}

我希望能够做到这一点:

let mut canvas = Canvas::new(100, 100, &renderer).color(Color::RGB(80, 230, 80));

我收到此错误:

错误:借来的值不够长 让 mut canvas = Canvas::new(100, 100, &renderer)

为什么返回的Canvas 对象的寿命不够长?如果我将结果存储在中间 let 中,那么它可以工作;为什么?

【问题讨论】:

  • 此代码无法在the playpen 上编译,特别是因为您引用了许多未定义的结构。请查看如何创建MCVE,并注意minimal部分。

标签: rust builder lifetime borrow-checker


【解决方案1】:

这是一个最小的复制:

#[derive(Debug)]
pub struct Canvas;

impl Canvas {
    fn new() -> Self {
        Canvas
    }

    fn color(&self) -> &Canvas {
        self
    }
}

fn main() {
    let mut canvas = Canvas::new().color();
    //             1 ^~~~~~~~~~~~~
    //                           2 ^~~~~
    println!("{:?}", canvas);
}

Rust 2015

error[E0597]: borrowed value does not live long enough
  --> src/main.rs:15:22
   |
15 |     let mut canvas = Canvas::new().color();
   |                      ^^^^^^^^^^^^^        - temporary value dropped here while still borrowed
   |                      |
   |                      temporary value does not live long enough
...
19 | }
   | - temporary value needs to live until here
   |
   = note: consider using a `let` binding to increase its lifetime

Rust 2018

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:15:22
   |
15 |     let mut canvas = Canvas::new().color();
   |                      ^^^^^^^^^^^^^        - temporary value is freed at the end of this statement
   |                      |
   |                      creates a temporary which is freed while still in use
...
18 |     println!("{:?}", canvas);
   |                      ------ borrow later used here
   |
   = note: consider using a `let` binding to create a longer lived value

出现问题是因为您创建了一个临时变量 (1),然后将该变量的引用传递给方法 (2),该方法返回该引用。在方法链的末尾,您试图返回引用并将其存储在变量中,但引用指向一个临时项,该项无处可住! Rust 不允许你引用无效的东西。

部分问题在于这个不是Builder模式,这只是一个使用链式方法调用修改自身的结构。一些解决方案:

  1. 存储“临时”变量,在这种情况下,所有方法都只是之后发生的正常突变方法。
  2. 接受self 而不是对自身的引用(&amp;self&amp;mut self),然后最终返回完整的结构。
  3. 在返回另一个独立结构而非引用的链末尾有一个build 方法。

【讨论】:

  • 你写的都是有道理的,但是为什么在我声明 canvas 变量时,Rust 没有给我一个错误?为什么允许声明以后在任何情况下都不能使用的东西?如果你删除println!("{:?}", canvas);,程序编译得很好,这有点误导,因为它让我相信绑定到canvas 变量是好的。但事实并非如此,而且永远不可能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
  • 2019-11-29
  • 2014-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多