Rust中向键为&str的HashMap插入key时如何处理生命周期问题
问题解决方案
错误根因
add_labeler方法使用不可变引用&self,无法修改结构体内部的HashMap字段,需要改为可变引用&mut self- 方法入参
tokens: Vec<&str>没有绑定结构体的生命周期'a,Rust 默认认为传入的字符串切片生命周期仅局限于方法调用周期,短于结构体要求的'a生命周期,因此不允许存入HashMap - 代码中
&self.label.insert(...)多写了不必要的取引用符号&,直接调用insert方法即可
方案一:保留生命周期标注使用 &'a str 作为键
如果你可以保证所有传入 add_labeler 的字符串切片生命周期都和结构体实例的生命周期完全一致,可以直接修改方法签名匹配生命周期即可:
impl<'a> LInstruction<'a> { // 原有new方法不变 pub fn add_labeler(&mut self, tokens: Vec<&'a str>) { let mut counter = 0; for token in tokens { if token.starts_with("(") && token.ends_with(")") { let label_name = token.trim_start_matches("(").trim_end_matches(")"); self.label.insert(label_name, counter); } counter += 1; } } }
该方案的局限在于:所有使用LInstruction结构体的上下文都需要处理生命周期约束,且无法存入运行时动态生成的字符串,使用限制较多。
方案二:使用 String 作为键(更推荐)
无需手动给每个字符串切片调用to_string(),可以通过迭代器批量处理,代码非常简洁:
use std::collections::HashMap; #[derive(Debug)] pub struct LInstruction { pub label: HashMap<String, u64> } impl LInstruction { pub fn new() -> LInstruction { LInstruction { label: [ ("R0", 0), ("R1", 1), ("R2", 2), ("R3", 3), ("R4", 4), ("R5", 5), ("R6", 6), ("R7", 7), ("R8", 8), ("R9", 9), ("R10", 10), ("R11", 11), ("R23", 12), ("R13", 13), ("R14", 14), ("R15", 15), ("SP", 0), ("LCL", 1), ("ARG", 2), ("THIS", 3), ("THAT", 4), ("SCREEN", 16384), ("KBD", 24576) ].into_iter().map(|(k, v)| (k.to_string(), v)).collect() } } pub fn add_labeler(&mut self, tokens: Vec<&str>) { let mut counter = 0; for token in tokens { if token.starts_with("(") && token.ends_with(")") { let label_name = token.trim_start_matches("(").trim_end_matches(")").to_string(); self.label.insert(label_name, counter); } counter += 1; } } }
该方案没有生命周期约束,使用更灵活,支持存储动态生成的标签字符串,对初学者来说心智负担更低,性能开销可以忽略不计。
内容的提问来源于stack exchange,提问作者aRtoo
相关产品推荐
相关产品推荐

