在其他结构中存储结构的引用
Store reference of struct in other struct
我有两个结构。 App
和 Item
.
我想要实现的是通过将可变引用传递给 Item
s 构造函数,将 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 app
或 item
会遇到同样的问题,因为地址会改变。
如果你有一个直接的树结构,我提倡简单地让父节点拥有子节点:
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);
}
我有两个结构。 App
和 Item
.
我想要实现的是通过将可变引用传递给 Item
s 构造函数,将 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 app
或 item
会遇到同样的问题,因为地址会改变。
如果你有一个直接的树结构,我提倡简单地让父节点拥有子节点:
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);
}