在 Rust 中,Box:ed 结构体与普通结构体相比,放置顺序有区别吗?

In Rust, is there a difference in drop order for a Box:ed struct compared to a plain struct?

提问人:Marcus Johansson 提问时间:11/10/2023 更新时间:11/10/2023 访问量:68

问:

以下代码不编译:

struct Ref<'a> {
    nbr: &'a u32,
}

fn func<'a>() {
    let nbr: u32 = 42;
    let _a_ref: Box<Ref<'a>> = Box::new(Ref { nbr: &nbr });
}

fn main() {
    func();
}

编译器抱怨说,它在结束时被丢弃,而仍然被借用。我基本上到处都搜索过,但我不明白为什么会发生这个错误。与声明相比,变量应该以相反的顺序删除,因此在删除之前应该删除包含引用的盒装,对吗?'nbr' does not live long enoughfunc()Refnbr

如果我变成:func()

fn func<'a>() {
    let nbr: u32 = 42;
    let _a_ref = Ref { nbr: &nbr };
}

它构建得很好!因此,盒装参考所需的寿命/范围存在一些差异 - 但我无法为这个看似基本的问题找到任何清晰简单的解释。

为了让它更加混乱,我注意到,如果我这样陈述类型:_a_ref

fn func<'a>() {
    let nbr: u32 = 42;
    let _a_ref: Ref<'a> = Ref { nbr: &nbr };
}

我再次收到错误。'nbr' does not live long enough

最后,我玩了下划线,如下所示:

fn func<'a>() {
    let nbr: u32 = 42;
    let _a_ref: Ref<'_> = Ref { nbr: &nbr };
}

现在它又构建得很好!这 3 种使用非装箱结构的方法有什么区别?它们与盒装变体相比如何?Ref

Rust 示波器 寿命

评论


答:

5赞 Chayim Friedman 11/10/2023 #1

这不是问题所在。Box'a

&nbr具有 的生存期。但是是调用方选择的生存期,它可能(甚至总是)大于 的生存期。因此,您不能分配给 .nbr'anbrRef<'nbr>Ref<'a>

Ref<'_>表示“让编译器推断生存期”,基本上等同于根本不指定类型。

评论

0赞 Marcus Johansson 11/10/2023
我想我很难理解 Rust 中生命周期概念的确切含义以及编译器如何应用它。我非常了解范围,而且它是不一样的。当你说这将大于 的寿命时,这意味着什么?为什么 Box 变体不编译?'anbr
1赞 Jmb 11/10/2023
@MarcusJohansson 如果你使用 ,变体会编译,它不会编译,因为你告诉编译器使用 ,并且由于来自调用者,所以它比函数持续时间更长。BoxBox<Ref<'_>>'a'a
0赞 Marcus Johansson 11/10/2023
啊,所以“调用者选择”的意思是,作为调用者(甚至只是一个实例化结构并将其绑定到变量的函数),提供参考并提及生存期,我基本上将定义这个生存期以包括我的完整范围,它“略高于”我作为调用者范围内的所有变量?因此,即使在删除作用域中的最后一个变量之后,也要求 in 是有效的引用。但是,在实践中,使用允许编译器推断生存期会使应用的生存期更接近 ?a&'a u32RefRef<'_>nbr
2赞 Jmb 11/10/2023
“呼叫者选择”意味着呼叫者将选择。你目前调用它的方式,在被调用之前开始,在它返回后结束,这确实只是“稍微”太长了。但是没有什么能阻止有人称它为 ,这需要引用才能永生。func'amain'afuncfunc::<'static>()