如何在结构中存储递归引用

时间:2015-10-21 16:33:06

标签: rust

让我们假设以下结构

struct Item<'a> {
    items: Vec<&'a Item<'a>>
}

我们假设以下变量包含许多Item个对象,其中包含空items字段。

let mut items: Vec<Item<'a>> = get_items();

我们假设我的任务是在每个items Item字段中添加对Item向量中所有其他items个对象的引用。< / p>

我目前的实施是

struct Item<'a> {
    items: Vec<&'a Item<'a>>,
}

impl<'a> Item<'a> {
    fn new() -> Item<'a> {
        Item { items: vec![] }
    }   
}

fn main() {
    let mut items = vec![Item::new(), Item::new()];
    while let Some(item) = items.pop() {
        for another_item in &mut items {
            item.items.push(another_item); 
        }   
        items.push(item);
    }   
}`

失败是因为我item.items.push(another_item);

2 个答案:

答案 0 :(得分:0)

你要做的事情是不健全的。在不了解您的用例的情况下,您的问题没有一个好的解决方案。

您有一些与可变性相关的错误。修复后,您的代码将变为:

struct Item<'a> {
    items: Vec<&'a Item<'a>>,
}

impl<'a> Item<'a> {
    fn new() -> Item<'a> {
        Item { items: vec![] }
    }   
}

fn main() {
    let mut items = vec![Item::new(), Item::new()];
    while let Some(mut item) = items.pop() {
        for another_item in items {
            item.items.push(&another_item); 
        }   
        items.push(item);
    }   
}

编译器现在抱怨another_item的生命周期:

  

错误:another_item活得不够长

for循环拥有another_item,并且无法将所有权归还给Vec引用。

无论你做什么,你都无法解决这个根本问题。这些规则背后的一个原因是引用实际上只是指针。当您将元素移入和移出items时,每个item都会更改其位置,从而使之前创建的指针无效。 (这不是Python,带有神奇的垃圾收集引用。)当然,Rust的规则可以防止这种情况发生。

答案 1 :(得分:0)

我结束了这段代码

use std::rc::Rc;
use std::cell::RefCell;

struct Item {
    items: Vec<Rc<RefCell<Item>>>,
}

fn main() {
    let items = vec![Item { items: Vec::new() }, Item { items: Vec::new() }];
    let iter = items.into_iter();
    let items = iter.map(|item| Rc::new(RefCell::new(item)));
    let items = items.collect::<Vec<_>>();
    for item_index in 0..items.len() {
        let item = items[item_index].clone();
        let mut item = item.borrow_mut();
        for another_item_index in 0..items.len() {
            if another_item_index == item_index {
                continue;
            }
            let another_item = items[another_item_index].clone();
            (*item).items.push(another_item);
        }
    }
}