【发布时间】:2020-06-26 19:40:37
【问题描述】:
我的心态是让我的Strings 不可变,这是一个单一的事实来源。
当我将同样的心态带入 Rust 时,我发现我必须做很多克隆。
由于Strings 没有改变,所有的克隆都是不必要的。
下面有一个例子和link to the relevant playground。
借用似乎不是一种选择,因为我必须处理引用及其生命周期。我的下一个想法是使用类似Rc 或Cow 结构的东西。但是用Rc 之类的东西包裹所有Strings 感觉不自然。在我有限的 Rust 经验中,我从未见过任何暴露的所有权/内存管理结构,即 Rc 和 Cow。我很好奇一个更有经验的 Rust 开发人员会如何处理这样的问题。
在 Rust 中公开所有权/内存管理结构,如 Rc 和 Cow 是否真的很自然?我应该使用切片吗?
use std::collections::HashSet;
#[derive(Debug)]
enum Check {
Known(String),
Duplicate(String),
Missing(String),
Unknown(String)
}
fn main() {
let known_values: HashSet<_> = [
"a".to_string(),
"b".to_string(),
"c".to_string()]
.iter().cloned().collect();
let provided_values = vec![
"a".to_string(),
"b".to_string(),
"z".to_string(),
"b".to_string()
];
let mut found = HashSet::new();
let mut check_values: Vec<_> = provided_values.iter().cloned()
.map(|v| {
if known_values.contains(&v) {
if found.contains(&v) {
Check::Duplicate(v)
} else {
found.insert(v.clone());
Check::Known(v)
}
} else {
Check::Unknown(v)
}
}).collect();
let missing = known_values.difference(&found);
check_values = missing
.cloned()
.fold(check_values, |mut cv, m| {
cv.push(Check::Missing(m));
cv
});
println!("check_values: {:#?}", check_values);
}
【问题讨论】:
-
在我有限的 Rust 经验中,我从未见过任何暴露的内存管理结构 --
String和Vec管理自己的内存,就像Rc是的。 -
在像 Java 这样的语言中,字符串是通过引用访问的,并且相同的对象被许多代码段共享。 Rust 不是这样工作的。所有权是明确的。您必须故意传递
&mut引用或类似的引用,以使其他一些代码改变您拥有的字符串。我认为你从另一种语言中继承了不适用于 Rust 的习惯。 -
@trentcl 这不是我的问题的重点。是的,我知道
String和Vec管理自己的记忆,但他们仍然屈服于所有权规则。我不能在不移动或借用的情况下通过String或Vec。这就是我在问题中关注Rc和Cow的原因。 -
@JohnKugelman 我使用多种语言工作,所以我很可能会继承另一种语言的习惯。
-
对于您的示例,所有字符串的生命周期都足够长,您可以在任何地方使用 &str。 play.rust-lang.org/…。如果可以的话,我倾向于使用 &str,并且只有在我真的需要独立拥有一个值或构造一个新值时才使用 String。
标签: memory-management rust ownership ownership-semantics