有没有办法在不可变地借用早期元素的同时向容器添加元素?

Is there a way to add elements to a container while immutably borrowing earlier elements?

我正在构建一个 GUI,我想将所有使用的纹理存储在一个地方,但我必须添加新的纹理,而旧的纹理已经被不变地借用了。

let (cat, mouse, dog) = (42, 360, 420); // example values

let mut container = vec![cat, mouse]; // new container

let foo = &container[0]; // now container is immutably borrowed

container.push(dog); // error: mutable borrow

是否有任何现有结构允许这样的事情, 或者我可以使用原始指针实现类似的东西吗?

绝对最简单的事情就是引入共享所有权:

use std::rc::Rc;

fn main() {
    let (cat, mouse, dog) = (42, 360, 420);
    let mut container = vec![Rc::new(cat), Rc::new(mouse)];
    let foo = container[0].clone();
    container.push(Rc::new(dog));
}

现在containerfoo共同拥有cat.

Is there any kind of existing structure that allows something like this,

是的,但总要权衡取舍。上面,我们使用了Rc来共享所有权,其中涉及到一个引用计数器。

另一种可能的解决方案是使用竞技场:

extern crate typed_arena;

use typed_arena::Arena;

fn main() {
    let container = Arena::new();
    let cat = container.alloc(42);
    let mouse = container.alloc(360);
    let dog = container.alloc(420);
}

这是不可索引的,您不能再次获得该值的所有权,也不能删除该值。

能够从集合中删除内容总是使无效引用变得危险。

can I implement something like this using raw pointers

几乎可以肯定。你会不会做对永远是一个棘手的问题。

but I have to add new textures while older textures are already immutably borrowed

很多时候,您没有做任何这样的事情。例如,您可以将逻辑分成多个阶段。你有两个容器;一个是人们参考的,另一个是收集新价值的。在该阶段结束时,您将两个集合合二为一。当然,您必须确保在阶段结束后不使用引用。