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

Rust所有权:实现可Push且支持成员不可变引用的向量容器

需求:支持Push操作且可持有成员不可变引用的不可变元素容器

核心诉求

我需要一个存储不可变元素的向量,既要能持有其成员的短生命周期不可变引用,又支持向其中添加元素。

我正在开发一个替代浮点数的精确算术crate,该crate需实现Copy trait。由于表达式是递归结构,我参考了将递归层级存入Vec的实现思路。

代码示例

enum ExprData{
  Val(u32),
  Const{ch: char, f64: f64},
  Sum(Vec<(u32, ExprRef)>)
}

#[derive(Clone, Copy)] // 实际需要自己实现Clone,否则会尝试克隆Field或者报错Field未实现Copy
struct FieldRef<'a> {  
  index: usize,        
  field: &'a Field
}

#[derive(Clone, Copy)]
enum ExprRef<'a> {
  Val(FieldRef<'a>),
  Const(FieldRef<'a>),
  Sum(FieldRef<'a>)
}

struct Field {
  members: SpecialContainer<ExprData>,
}

impl Field {
  fn parse(&mut self, input: &str) -> ExprRef {
    assert_eq!(input, "π+1");
    let idx0 = self.maybe_add(ExprData::Const{ch: 'π', f64: f64::consts::PI});
    let idx1 = self.maybe_add(ExprData::Val(1));
    let idx2 = self.maybe_add(ExprData::Sum(vec![(1,ExprRef::Const(FieldRef{field: self, index: idx0})),(1,ExprRef::Val(FieldRef{field: self, index: idx1}))]));
    ExprRef::Sum(FieldRef{field: self, index: idx2})
  }

  fn maybe_add(&mut self, data: ExprData) -> usize {
    match self.members.position(&data) { // 需要判断相等性,用不可变引用最优;克隆求和向量效率极低
      Some(p) => p,                     
      None => {                         
        self.members.push(data); // 核心矛盾点:Push操作会导致已有引用失效
        self.members.len()-1
      }
    }
  }
}

fn main () {
  // Field: []
  let mut f = Field { members: SpecialContainer::new() };
  let pi_one: ExprRef = f.parse("π+1"); //
  // Field: [π, 1, 1+π]
  let two_pi_one = pi_one + pi_one;
  // collect_like_terms([f.get_sum(pi_one),f.get_sum(pi_one)].concat())
  // [1+π] + [1+π] -> [(1,1),(1,π),(1,1),(1,π)] -合并同类项-> [(2,1),(2,π)]
  // field.maybe_add(ExprData::Sum([(2,1),(2,π)])
  // Field: [π, 1, 1+π, 2+2π]
}

已考虑的方案

  • Vec<OnceCell<ExprData>>:不支持Push操作,因为Push可能会移动数据,导致已有引用失效
  • HashSet<ExprData>:不确定扩容时是否会移动数据,无法安全插入同时保留引用
  • RefCell<Vec<ExprData>>:每次访问都需要克隆ExprData,不符合避免克隆的需求
  • LinkedList<[OnceCell<ExprData>; CHUNK_SIZE]>:可行,但LinkedList追加仍需可变引用,不过Push不会移动底层数据
  • AppendList<ExprData>:功能符合需求,但实现复杂度较高
  • 基于Cow的实现:暂未明确可行路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:04:53