Struct 如何从Option::unwrap\u或返回新结构?

Struct 如何从Option::unwrap\u或返回新结构?,struct,rust,lifetime,Struct,Rust,Lifetime,我有一个HashMap,它使用char作为键,使用struct作为值 HashMap的get()方法通常会使用HashMap中没有的键调用,因此我想在返回选项上使用unwrap\u或()来创建默认的struct值。但是,当我尝试这样做时,编译器抛出以下错误(我尝试返回的默认值为temp): 这是一台小型复制机: struct Sample { thing: i32 } fn do_stuff() { let map = HashMap::<char, Sample>

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

HashMap的
get()
方法通常会使用HashMap中没有的键调用,因此我想在返回选项上使用
unwrap\u或()
来创建默认的
struct
值。但是,当我尝试这样做时,编译器抛出以下错误(我尝试返回的默认值为
temp
):

这是一台小型复制机:

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
    });
}
struct示例{
事情:i32
}
fn do_stuff(){
let map=HashMap:::new();
让sample=map.get(&'a')。展开或({
让温度=样品{
事情:0
};
&临时工
});
}
我有两个问题:

  • 有没有办法延长
    temp
    绑定的寿命
  • 在使用选项时,是否有更好的方法回退到默认的
    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 }
        })
    }
    

    请注意,您的问题表明您有一个根本的误解:

    如何返回新结构

    但是你的代码是这样的:

    &temp
    
    这是对结构的引用。问题是,您的结构仅在作为参数传递给
    unwrap\u或
    的块的持续时间内有效。块一结束,所有未从块返回的变量都将被删除,从而使对它们的任何引用无效

    有没有办法延长临时绑定的寿命

    有一种方法可以延长绑定的寿命:将其移动到代码中的位置。如果更早地创建变量,则其生命周期开始得更早。这就是工作的原因


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

    不知何故,我忽略了您可以像#3中那样向前声明绑定。我想我在铁锈书或其他任何地方都没有看到任何使用转发声明的情况。谢谢
    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
            }
        };
    }
    
    &temp