【发布时间】:2021-12-20 02:36:34
【问题描述】:
围绕这个问题有很多问题,解决方案大多是“使用Entry”。
但是这是一个问题,因为HashMap::entry() 需要一个拥有的值,这意味着即使密钥已经存在并且我们只想就地更新值,这也意味着可能昂贵的副本/分配,因此使用get_mut。然而,在对本地的引用上使用 get_mut 会导致 rustc 假设所述引用被存储到哈希图中,并且 thus that returning the hashmap is an error:
use std::borrow::Cow;
use std::collections::HashMap;
fn get_string() -> String { String::from("xxxxxxx") }
fn foo() -> HashMap<Cow<'static, str>, usize> {
let mut v = HashMap::new();
// stand-in for "get a string slice as key",
// real case is getting a String from an
// mpsc and the key being a segment of that string
let s = get_string();
// stand-in for a structure which contains an `Option<Cow>`
let k = Cow::from(&s[2..3]);
// because of get_mut, `&s` is apparently considered to be stored in `v`?
if let Some(e) = v.get_mut(&k) {
*e += 1;
} else {
v.insert(Cow::from(k.into_owned()), 0);
}
v
}
请注意,第 9~13 行的操作是为了阐明模式的要点,但get_mut alone is sufficient to trigger the issue
有没有办法不影响效率,还是急切分配是唯一的办法? (注意:因为这是一个静态问题,像contains_key 或get 这样的动态门显然不会做任何事情。
【问题讨论】:
-
在这里使用 Cow 没有什么意义,你也应该更喜欢 entry,或者在你的情况下 entry_raw
-
@Stargateur 如 cmets 中所述,
Cow充当更复杂结构(包含牛)的替身。我猜raw_entry_mut可能会工作,但它需要每晚仍然...... -
@Stargateur 显然是 it's being rejected 无论如何,因此建立它似乎是一个糟糕的主意。
-
为了更加清晰,我试图将代码从字符串(非结构化且为了效率起见具有有限的灵活性)更新为更丰富的 enums-with-strings-as-associated-data... 当然由于 Borrow 的语义,你不能真正创建非平凡结构之间的关系,因为
Borrowed总是通过引用返回。 -
嗯,你可以直接拥有Cow,但那样可能会失去Cow本身的用途? play.rust-lang.org/…