gpt4 book ai didi

rust - 父<->子关系所有权问题

转载 作者:行者123 更新时间:2023-12-03 11:36:57 27 4
gpt4 key购买 nike

我刚刚开始学习Rust,并且在理解所有权如何在我的案例中遇到一些麻烦:

use std::ops::IndexMut;

// ================================================

struct Container {
root: Option<ContainerItem>,
items: Vec<ContainerItem>
}

impl Container {
pub fn create_item(&mut self) -> usize {
let item = create_test_item();
let idx = self.items.len();
self.items.push(item);
return idx;
}

pub fn get_item(&mut self, index: usize) -> &mut ContainerItem {
return self.items.index_mut(index);
}

pub fn new() -> Container {
let mut x = Container {
root: None,
items: Vec::new()
};

x.root = Some(create_test_item());

return x;
}
}

// ================================================

struct ContainerItem {
idx: usize,
children: Vec<usize>,
parent: usize,
has_parent: bool
}

impl ContainerItem {
pub fn add_child(&mut self, value: &mut ContainerItem) {
value.parent = self.idx;
value.has_parent = true;
self.children.push(value.idx);
}
}

// ================================================

fn create_test_item() -> ContainerItem {
ContainerItem {
idx: 1,
children: Vec::new(),
parent: 0,
has_parent: false
}
}

fn main() {
let mut container = Container::new();

let item_index = container.create_item();
let item = container.get_item(item_index);

if let Some(mut root) = container.root {
root.add_child(item);
}
}
我有一个 ContainerContainerItem。每个 ContainerItem可以有子代,也有对其父代的引用(子代和父代都作为其索引存储在 Containeritems vec中)。一切都很好,向容器中添加项目是可行的,但是当我尝试向 Container的根项目(这是 ContainerItem)中添加子项时,会引发错误:
error[E0503]: cannot use `container.root` because it was mutably borrowed
--> src/main.rs:68:12
|
66 | let item = container.get_item(item_index);
| --------- borrow of `container` occurs here
67 |
68 | if let Some(mut root) = container.root {
| ^^^^^^^^^^^^^^ use of borrowed `container`
69 | root.add_child(item);
| ---- borrow later used here

error[E0505]: cannot move out of `container.root.0` because it is borrowed
--> src/main.rs:68:17
|
66 | let item = container.get_item(item_index);
| --------- borrow of `container` occurs here
67 |
68 | if let Some(mut root) = container.root {
| ^^^^^^^^ move out of `container.root.0` occurs here
69 | root.add_child(item);
| ---- borrow later used here
如果我将调用更改为 add_child以用于例如 create_test_item()作为参数,则可以正常工作。
我认为这可能是因为 Containeritems字段对所有 ContainerItem都拥有所有权?但是我通过引用 add_child传递了它,所以我认为这没关系,因为我没有更改所有者?

最佳答案

我认为麻烦来自这样一个事实,在这种父←→子关系中,有时会用引用和索引来引用项目。
因此,并不总是很清楚,何时借款应该涉及整个容器或仅涉及其中一部分的一个项目。
而且,根项不会与其他项存储在同一位置,因此无法使用索引来引用它。
我重新组织了您的代码,以便始终依靠索引(据我所知,您的意图是这样;也许它并不总是等同于您最初想要的)。
这样一来,一旦我们不得不调整许多指数,我们就将整个容器作为借口了。
因此,add_child()方法从项实现移至容器。
请注意,has_parent bool 值也是切换到Option的好机会。
还请注意,只要我们借用get_item()get_item_mut()的商品,就不能创建新商品,因为Vec内部的重新分配可能会使引用无效;借方检查员将禁止这样做。

pub struct Container {
root: Option<usize>, // why not implicitly alway 0?
items: Vec<ContainerItem>,
}

impl Container {
pub fn create_item(&mut self) -> usize {
let idx = self.items.len();
let item = create_test_item(idx);
self.items.push(item);
idx
}

pub fn get_item(
&self,
index: usize,
) -> &ContainerItem {
&self.items[index]
}

pub fn get_item_mut(
&mut self,
index: usize,
) -> &mut ContainerItem {
&mut self.items[index]
}

pub fn new() -> Container {
let mut this = Container {
root: None,
items: Vec::new(),
};
this.root = Some(this.create_item());
this
}

pub fn add_child(
&mut self,
parent_idx: usize,
child_idx: usize,
) {
// forget child in previous parent if any
if let Some(prev_parent_idx) = self.items[child_idx].parent {
let prev_children = &mut self.items[prev_parent_idx].children;
let idx = prev_children.iter().position(|i| *i == child_idx);
prev_children.remove(idx.unwrap());
}
// give the child its new parent
let child = &mut self.items[child_idx];
child.parent = Some(parent_idx);
// append this new child to the parent
let parent = &mut self.items[parent_idx];
parent.children.push(child_idx);
}
}

#[derive(Debug)]
pub struct ContainerItem {
idx: usize,
children: Vec<usize>,
parent: Option<usize>,
}

fn create_test_item(idx: usize) -> ContainerItem {
ContainerItem {
idx,
children: Vec::new(),
parent: None,
}
}

fn main() {
let mut container = Container::new();
let item_idx = container.create_item();
println!("item: {:?}", container.get_item(item_idx));

if let Some(root_idx) = container.root {
println!("root: {:?}", container.get_item(root_idx));
println!("~~~~~~~~");
container.add_child(root_idx, item_idx);
println!("item: {:?}", container.get_item(item_idx));
println!("root: {:?}", container.get_item(root_idx));
}
}

关于rust - 父<->子关系所有权问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64024666/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com