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

lsc*_*rer 3 rust

我有两个结构.AppItem.

我想要实现的是通过将可变引用传递给s构造函数来在结构Itemitems向量中存储.AppItem

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);;
}
Run Code Online (Sandbox Code Playgroud)

该代码产生以下错误:

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

有没有办法做到这一点?

She*_*ter 5

虽然Rc对于您的用例可能是正确的,但是理解为什么您会收到错误是很好的.请阅读为什么我不能在同一个结构中存储值和对该值的引用?因为它有更深入的讨论,为什么你的代码不能按原样运行.简化说明如下.

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

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

在这里,我们Item在某个地址的堆栈上创建一个新的.我们假装地址是0x1000.然后我们取item(0x1000)的地址并将其存储在Vec内部App.然后我们返回item到调用函数,该函数驻留在不同的堆栈帧中.这意味着地址item会改变,这意味着0x1000不再保证指向有效Item!这就是Rust阻止你制作整类内存错误的方法!

我会说你通常会把它写成:

fn main() {
    let item = Item;
    let mut app = App::new();
    app.register_item(&item);
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试返回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);
}
Run Code Online (Sandbox Code Playgroud)