我如何 return 来自 Option::unwrap_or 的新结构?

How do I return a new struct from Option::unwrap_or?

我有一个 HashMap,它使用 char 作为键,使用 struct 作为值。

HashMap 的 get() 方法通常会使用不在 HashMap 中的键调用,所以我想在 returned 选项上使用 unwrap_or() 创建一个默认 struct 值。但是,当我尝试这样做时,编译器会抛出以下错误(temp 是我尝试 return 的默认值):

lib.rs:51:4: 51:8 error: `temp` does not live long enough

这里是一个小复制器:

struct Sample {
    thing: i32
}

fn do_stuff() {
    let map = HashMap::<char, Sample>::new();

    let sample = map.get(&'a').unwrap_or({
        let temp = Sample {
            thing : 0
        };
        &temp
    });
}

我有两个问题:

  1. 有没有办法让 temp 绑定的寿命更长?
  2. 有没有更好的方法在使用选项时回退到默认 struct

对于您的精确场景,您可以这样做:

use std::collections::HashMap;
struct Sample {
    thing : i32
}

fn main() {
    let map = HashMap::<char, Sample>::new();
    let temp = Sample { thing : 0 };
    let sample = map.get(&'a').unwrap_or(&temp);
}

不过,通常情况下,您想要更像这样的东西:

use std::collections::HashMap;
#[derive(Clone)]
struct Sample {
    thing : i32
}

fn get_sample(map: &HashMap<char, Sample>) -> Sample
{
    map.get(&'a').cloned().unwrap_or_else(|| {
        Sample { thing : 0 }
    })
}

如果真的想条件初始化取局部变量的地址是可以的,但是不能写成unwrap_or或者unwrap_or_else:

use std::collections::HashMap;
struct Sample {
    thing : i32
}

fn main() {
    let map = HashMap::<char, Sample>::new();
    let temp;
    let sample = match map.get(&'a') {
        Some(sample) => sample,
        None => {
            temp = Sample { thing : 0 };
            &temp
        }
    };
}

请注意,您的问题表明您存在根本误解:

How do I return a new struct

但是你的代码是这样的:

&temp

这是对结构的引用。问题是您的结构仅在作为参数传递给 unwrap_or 的块的持续时间内存在。一旦该块结束,任何未从块中 return 编辑的变量都会被删除,从而使对它们的任何引用无效。

Is there a way to make the temp binding live longer?

有一种方法可以延长绑定的生命周期:移动它在代码中的位置。如果您更早地创建一个变量,它的生命周期就会更早开始。这就是 起作用的原因。

如果您将代码更改为 return 结构而不是引用,那么这就解释了第二个解决方案的工作原理,并且更好地匹配您对问题建模的方式。但是,您不能总是廉价地从引用转到非引用,有时甚至是不可能的。