web-dev-qa-db-fra.com

Comment créer une structure simple d'enfants parents avec les références simples?

Je veux stocker une collection d'enfants qui tiennent chacun une référence à son parent.

L'exemple suivant ne compilera pas ( terrain de je ).

struct Parent<'p> {
    children: Vec<Child<'p>>,
}

struct Child<'p> {
    parent: &'p Parent<'p>
}

fn main() {
    let mut parent = Parent {children: vec![]};
    let child = Child{parent: &parent};
    parent.children.Push(child);
}

Existe-t-il un moyen de créer une telle référence cyclique sans introduire des pointeurs intelligents mais avec des références simples? Peut-être qu'un peu de danger peut aider?

Sinon, à quoi choisir un exemple de travail minimal?

[~ # ~] upd [~ # ~ ~] : Pour que le parent ne soit pas abandonné pendant la création d'un enfant, introduisons une spéciale Méthode de Parent, mais elle ne compilera pas non plus pour une raison évidente:

impl<'p> Parent<'p> {
    fn add_child(&'p mut self) {
        let child = Child{parent: &self};
        self.children.Push(child);
    }
}

upd2 : Et s'il n'y a peut-être pas d'enfants "orphelins" et ils devraient toujours appartenir à un parent?

3
tsionyx

Eh bien, Ceci compile: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de9618B8B7425F8B1E77E6065D76B19

struct Parent {
    children: Vec<Child>,
}

struct Child {
    parent: *const Parent
}

fn main() {
    let mut parent = Parent {children: vec![]};
    let child = Child{parent: &parent as *const Parent};
    parent.children.Push(child);
}

Mais ensuite, bien sûr, à la désarférence, le pointeur brut vous aurez besoin de blocs dangereux:

let first_child = &parent.children[0];
let the_parent = unsafe { &*first_child.parent};

Edit: Ajoutons un peu de discussion, cependant. Le code ci-dessus fait, dans un sens très littéral, quelle op demande. Cependant, il y a certainement des défauts ici. Plus important encore, il est maintenant au programmeur en utilisant Parent et Child pour que aucune merde étrange ne se produit. Si vous initialisez un enfant avec un parent, puis le parent est déplacé, Boom, le pointeur désigne maintenant quelque chose qu'il ne devrait pas être dirigé vers.

Donc, maintenant, l'exigence devient: un parent d'un enfant ne doit jamais être déplacé; Ou, si le parent est ému, le pointeur parent de chacun de ses enfants doit être mis à jour.

Afin de faire respecter cela, vous devriez probablement encapsuler vos trucs de pointe bruts d'une manière ou d'une autre; La raison pour laquelle je n'ai pas écrit à ce sujet est que vous avez spécifiquement dit "aucun point de pointe intelligent" et que vous vous sentez comme tout ce qui vous aide à faire respecter les exigences de sécurité sera une forme de pointeur intelligent plus ou moins sophistiqué.

0
Lagerbaer