我如何 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
});
}
我有两个问题:
- 有没有办法让
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 }
})
}
如果真的想条件初始化取局部变量的地址是可以的,但是不能写成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 结构而不是引用,那么这就解释了第二个解决方案的工作原理,并且更好地匹配您对问题建模的方式。但是,您不能总是廉价地从引用转到非引用,有时甚至是不可能的。
我有一个 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
});
}
我有两个问题:
- 有没有办法让
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 }
})
}
如果真的想条件初始化取局部变量的地址是可以的,但是不能写成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 结构而不是引用,那么这就解释了第二个解决方案的工作原理,并且更好地匹配您对问题建模的方式。但是,您不能总是廉价地从引用转到非引用,有时甚至是不可能的。