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

半城伤御伤魂 提交于 2019-12-12 23:15:34

问题


I'm building a GUI and I want to store all used textures in one place, but I have to add new textures while older textures are already immutably borrowed.

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

Is there any kind of existing structure that allows something like this, or can I implement something like this using raw pointers?


回答1:


The absolute easiest thing is to introduce shared ownership:

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));
}

Now container and foo jointly own cat.

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

Yes, but there are always tradeoffs. Above, we used Rc to share ownership, which involves a reference counter.

Another potential solution is to use an arena:

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);
}

This isn't indexable, you cannot take ownership of the value again, and you cannot remove a value.

Being able to remove things from the collection always makes invalidating references dangerous.

can I implement something like this using raw pointers

Almost certainly. Will you get it right is always the tricky point.

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

Many times, you don't have to do any such thing. For example, you can split up your logic into phases. You have two containers; one that people take references into, and another to collect new values. At the end of the phase, you combine the two collections into one. You have to ensure that no references are used after the end of the phase, of course.



来源:https://stackoverflow.com/questions/45306527/is-there-a-way-to-add-elements-to-a-container-while-immutably-borrowing-earlier

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!