2017-07-25 8 views
1

Je suis en train de créer une interface graphique et je veux stocker toutes les textures utilisées en un seul endroit, mais je dois ajouter de nouvelles textures alors que les textures plus anciennes sont déjà immuablement empruntées.Existe-t-il un moyen d'ajouter des éléments à un conteneur tout en empruntant de manière immuable des éléments antérieurs?

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 

Y at-il une telle structure existante qui permet quelque chose comme ça, ou puis-je mettre en œuvre quelque chose comme cela à l'aide des pointeurs premières?

Répondre

3

La meilleure chose absolue est d'introduire propriété partagée:

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

maintenant containeretfoo possèdent conjointement cat.

Y at-il une telle structure existante qui permet quelque chose comme ça,

Oui, mais il y a toujours des compromis. Ci-dessus, nous avons utilisé Rc pour partager la propriété, ce qui implique un compteur de référence.

Une autre solution possible est d'utiliser une arène:

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

Ce n'est pas indexables, vous ne pouvez pas prendre possession de la valeur à nouveau, et vous ne pouvez pas supprimer une valeur.

Etre capable de retirer des choses de la collection toujours rend les références invalidantes dangereuses.

puis-je mettre en œuvre quelque chose comme cela en utilisant des pointeurs premières

Presque certainement. Serez-vous le droit est toujours le point délicat.

mais je dois ajouter de nouvelles textures tandis que les textures plus anciennes sont déjà empruntés immuablement

Plusieurs fois, vous ne ont de faire une telle chose. Par exemple, vous pouvez diviser votre logique en plusieurs phases. Vous avez deux conteneurs; celui auquel les gens prennent des références, et un autre pour recueillir de nouvelles valeurs. À la fin de la phase, vous combinez les deux collections en une seule. Vous devez vous assurer qu'aucune référence n'est utilisée après la fin de la phase, bien sûr.