在其他结构中存储结构的引用

Store reference of struct in other struct

我有两个结构。 AppItem.

我想要实现的是通过将可变引用传递给 Items 构造函数,将 Item 存储在 App 结构的 items 向量中。

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

impl<'a> App<'a> {
    pub fn new() -> App<'a> {
        App { items: Vec::new() }
    }
    pub fn register_item(&mut self, item: &'a Item) {
        self.items.push(item);
    }
}

pub struct Item;

impl Item {
    pub fn new(app: &mut App) -> Item {
        let item = Item;
        app.register_item(&item);
        item
    }
}

fn main() {
    let mut app = App::new();

    let item = Item::new(&mut app);;
}

代码抛出以下错误:

test.rs:8:28: 8:32 error: `item` does not live long enough
test.rs:8         app.register_item(&item);

有什么办法吗?

简单的解决方案是使用 Rc

use std::rc::Rc;

pub struct Item;

impl Item {

    pub fn new(app: &mut App) -> Rc<Item> {
        let item = Rc::new(Item);
        app.register_item(item.clone());
        item
    }

}

pub struct App {
    items: Vec<Rc<Item>>
}

...

虽然 Rc 对于您的用例可能是正确的,但最好了解您为什么会遇到错误。请阅读 ,因为它对为什么您的代码不能按原样工作进行了更深入的讨论。下面是一个简化的解释。

让我们看看你的构造函数:

fn new(app: &mut App) -> Item {
    let item = Item;
    app.register_item(&item);
    item
}

在这里,我们在堆栈的某个地址创建了一个新的 Item。让我们假设地址是 0x1000。然后,我们将 item (0x1000) 的地址存储到 App 内部的 Vec 中。然后我们 return item 调用函数,它驻留在 不同的堆栈帧 中。也就是说item的地址会变,也就是说0x1000不再保证指向一个有效的Item!这就是 Rust 防止您犯 类 整个内存错误的方式!

我会说你通常会看到这样写的:

fn main() {
    let item = Item;
    let mut app = App::new();
    app.register_item(&item);
}

如果您尝试从此函数 return appitem 会遇到同样的问题,因为地址会改变。


如果你有一个直接的树结构,我提倡简单地让父节点拥有子节点:

struct App {
    items: Vec<Item>
}

impl App {
    fn new() -> App {
        App { items: Vec::new() }
    }

    fn register_item(&mut self, item: Item) {
        self.items.push(item);
    }
}

pub struct Item;

fn main() {
    let mut app = App::new();
    app.register_item(Item);
}