将结构的引用存储在其他结构中 [英] Store reference of struct in other struct

查看:29
本文介绍了将结构的引用存储在其他结构中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个结构体.AppItem.

I have two structs. App and Item.

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

What I want to achieve is to store an Item in the items vector of the App struct by passing a mutable reference to the Items constructor.

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

有没有办法做到这一点?

Is there any way to do this?

推荐答案

虽然 Rc 可能适用于您的用例,但最好理解为什么会出现这样的错误.请阅读为什么我不能在同一个结构中存储一个值和对该值的引用?,因为它有很多更深入地讨论为什么您的代码不能按原样工作.下面是一个简单的解释.

While Rc might be correct for your use case, it's good to understand why you are getting the error you are. Please read Why can't I store a value and a reference to that value in the same struct? as it has a much more in-depth discussion about why your code cannot work as-is. A simplified explanation follows.

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

Let's look at your constructor:

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

在这里,我们在堆栈上的某个地址创建了一个新的 Item.让我们假设地址是 0x1000.然后我们将 item 的地址(0x1000)存储到 App 内的 Vec 中.然后我们将 item 返回给调用函数,该函数位于不同的堆栈帧中.那意味着item的地址会改变,也就意味着0x1000不再保证指向一个有效的Item!这就是 Rust 防止你犯整类内存错误的方式!

Here, we create a new Item on the stack at some address. Let's pretend that address is 0x1000. We then take the address of item (0x1000) and store it into the Vec inside the App. We then return item to the calling function, which resides in a different stack frame. That means that the address of item will change, which means that 0x1000 is no longer guaranteed to point to a valid Item! This is how Rust prevents you from making whole classes of memory errors!

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

I'd say that you'd normally see this written as:

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

如果你试图从这个函数返回 appitem 也会有同样的问题,因为地址会改变.

This will have the same problem if you tried to return app or item from this function, as the address will change.

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

If you have a straight-forward tree structure, I'd advocate for simply letting the parent nodes own the children:

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

这篇关于将结构的引用存储在其他结构中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆