You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Rust HashMap or_insert更新结构体无需解引用即可生效?

关于Rust HashMap中Entry返回值的解引用困惑

根据Rust官方文档中的示例,下面代码里的count变量必须通过解引用(*)才能正常工作:

let text = "hello world wonderful world";

let mut map = HashMap::new();

for word in text.split_whitespace() {
    let count = map.entry(word).or_insert(0);
    *count += 1;
}

println!("{:?}", map);

但我自己写的代码里,在HashMap找到对应键后更新结构体中的u8类型变量(team_val.goals_scored)时,不需要解引用就能正常运行。我本来以为更新HashMap中的结构体内容时必须解引用,这让我很困惑。

我的代码:

#[derive(Debug)]
struct Team {
    name: String,
    goals_scored: u8,
    goals_conceded: u8,
}

fn build_scores_table(results: String) -> HashMap<String, Team> {
    // 球队名称作为键,对应的结构体作为值
    let mut scores: HashMap<String, Team> = HashMap::new();

    for r in results.lines() {
        let v: Vec<&str> = r.split(',').collect();
        let team_1_name = v[0].to_string();
        let team_1_score: u8 = v[2].parse().unwrap();
        let team_2_name = v[1].to_string();
        let team_2_score: u8 = v[3].parse().unwrap();

        // 从当前行提取数据填充分数表:team_1的进球数是team_2的失球数,反之亦然
        let mut team_1_struct= Team {
            name: team_1_name.clone(),
            goals_scored: team_1_score,
            goals_conceded: team_2_score
        };

        let mut team_2_struct= Team {
            name: team_2_name.clone(),
            goals_scored: team_2_score,
            goals_conceded: team_1_score
        };

        if scores.contains_key(&team_1_name) {
            let team_val = scores.entry(team_1_name.clone()).or_insert(team_1_struct);
            println!("Yooo {:#?}",team_val);

            team_val.goals_scored +=team_1_score;
            team_val.goals_conceded += team_2_score;
        } else {
            scores.insert(team_1_name,team_1_struct);
        }

        if scores.contains_key(&team_2_name) {
            let team_val = scores.entry(team_2_name.clone()).or_insert(team_2_struct);
            println!("Yooo {:#?}",team_val);

            team_val.goals_scored +=team_2_score;
            team_val.goals_conceded += team_1_score;
        } else {
            scores.insert(team_2_name,team_2_struct);
        }
    }
    scores
}

原因解释

这两种情况的核心区别在于**entry().or_insert()返回的引用类型,以及Rust的自动解引用规则**:

  1. 官方文档示例中,or_insert(0)返回的是&mut i32(对整数的可变引用)。+=运算符需要直接操作i32值本身,因此必须显式解引用这个引用,才能让运算符作用到底层的整数上。

  2. 你的代码中,or_insert(team_1_struct)返回的是&mut Team(对结构体的可变引用)。当你通过team_val.goals_scored访问结构体字段时,Rust会自动触发自动解引用(Deref coercion),帮你省略掉显式的*操作——team_val.goals_scored等价于(*team_val).goals_scored,因此无需手动解引用就能直接修改结构体内部的字段。

简单总结:

  • 对基本类型的可变引用执行赋值/运算时,需要显式解引用
  • 对结构体/枚举的可变引用访问字段时,Rust会自动完成解引用,无需手动添加*

内容的提问来源于stack exchange,提问作者WowBow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 07:05:21