【问题标题】:Builder pattern - borrowed value does not live long enough建造者模式——借来的价值活得不够长
【发布时间】:2015-04-06 09:04:56
【问题描述】:

我正在尝试实现一个简单的构建器,但在生命周期中挣扎。以下是给error: borrowed value does not live long enoughThis question 看起来很相似。如果我将t 存储在一个可变变量中,然后调用s 并最终确定它可以工作,但我想让一个班轮工作。我究竟做错了什么?

struct Type<'a> {
    s: &'a String,
}

struct TypeBuilder {
    s: String,
}

impl TypeBuilder {
    fn new() -> TypeBuilder {
        TypeBuilder { s: "".to_string() }
    }

    fn s(&mut self, s: String) -> &mut TypeBuilder {
        self.s = s;
        self
    }

    fn finalize(&self) -> Type {
        Type { s: &self.s }
    }
}

fn main() {
    let t = TypeBuilder::new()
                    .s("a".to_string())
                    .finalize();
    println!("string: {}", t.s);
}

【问题讨论】:

标签: rust


【解决方案1】:

问题是您正在使用基于来自TypeBuilderString 的字符串切片创建Type,但是使用new() 创建的TypeBuilder 实例在同一个let 语句中被立即销毁,因此,如果允许这样做,字符串切片将变得悬空。这就是为什么当您首先将 TypeBuilder 存储在变量中时它会起作用的原因。

您使用构建器的方法的问题在于,构建器是其所构建价值的数据的所有者:Type 引用了TypeBuilder 的内容。这意味着Type 实例始终与TypeBuilder 实例相关联,您不能创建Type 并删除TypeBuilder。然而,这真的很不自然 - 构建器通常是临时对象,仅在构建期间才需要。

因此,为了使构建器模式正常工作,您的 Type 必须成为数据的所有者:

struct Type {
    s: String,
}

那么builder应该是传值,然后被finalize()消费:

impl TypeBuilder {
    fn new() -> TypeBuilder {
        TypeBuilder { s: "".to_string() }
    }

    fn s(mut self, s: String) -> TypeBuilder {
        self.s = s;
        self
    }

    fn finalize(self) -> Type {
        Type { s: self.s }
    }
}

这样您的构建代码应该可以完全按原样工作。

【讨论】:

  • 太棒了,谢谢。这实际上与我开始使用的相似,但我遇到了问题,我想是因为我在修饰函数中使用了&amp;mut self,而不是使用mut self
  • 你知道他们为什么使用&amp;mut selfhere吗?
  • &amp;mut self/&amp;self 的方法在那里有效,因为那里的构建器仅适用于 Copy 数据,并且构建器构建的结构不包含对构建器的引用。它不适用于Strings 和其他类型的拥有的不可复制数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 2020-07-23
  • 2019-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多