xud*_*fsd 3 linked-list smart-pointers rust
我正在尝试实现一个链表来理解 Rust 中的智能指针。我定义了一个Node:
use std::{cell::RefCell, rc::Rc};
struct Node {
val: i32,
next: Option<Rc<RefCell<Node>>>,
}
Run Code Online (Sandbox Code Playgroud)
并像这样迭代
fn iterate(node: Option<&Rc<RefCell<Node>>>) -> Vec<i32> {
let mut p = node;
let mut result = vec![];
loop {
if p.is_none() {
break;
}
result.push(p.as_ref().unwrap().borrow().val);
p = p.as_ref().unwrap().borrow().next.as_ref();
}
result
}
Run Code Online (Sandbox Code Playgroud)
编译器报错:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:27:13
|
27 | p = p.as_ref().unwrap().borrow().next.as_ref();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -
| | |
| | temporary value is freed at the end of this statement
| | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, Node>`
| creates a temporary which is freed while still in use
| a temporary with access to the borrow is created here ...
|
= note: consider using a `let` binding to create a longer lived value
Run Code Online (Sandbox Code Playgroud)
发生了什么?我们不能使用引用来迭代以这种方式定义的节点吗?
您需要克隆以下内容,而不是分配p借用的引用Rc:
use std::cell::RefCell;
use std::rc::Rc;
struct Node {
val: i32,
next: Option<Rc<RefCell<Node>>>,
}
fn iterate(node: Option<Rc<RefCell<Node>>>) -> Vec<i32> {
let mut p = node;
let mut result = vec![];
loop {
let node = match p {
None => break,
Some(ref n) => Rc::clone(n), // Clone the Rc
};
result.push(node.as_ref().borrow().val); //works because val is Copy
p = match node.borrow().next {
None => None,
Some(ref next) => Some(Rc::clone(next)), //clone the Rc
};
}
result
}
fn main() {
let node = Some(Rc::new(RefCell::new(Node {
val: 0,
next: Some(Rc::new(RefCell::new(Node { val: 1, next: None }))),
})));
let result = iterate(node);
print!("{:?}", result)
}
Run Code Online (Sandbox Code Playgroud)
这是必要的,因为您尝试在需要较长寿命的上下文中使用寿命较短的变量。的结果p.as_ref().unwrap().borrow()在循环迭代后被删除(即释放、取消分配),但您试图在下一个循环中使用其成员(这被称为,use after freeRust 的设计目标之一就是防止这种情况发生)。
问题是借用者并不拥有该对象。如果你想在下一个循环中使用nextas ,那么就必须拥有该对象。这可以通过(即“引用计数”)来实现,并允许在单个线程中存在多个所有者。 ppRc
如果 的定义
Node::next是Option<Box<RefCell<Node>>>,如何迭代这个列表?
是的,我也对 感到非常困惑
RefCell,如果RefCell我们不能仅使用引用来迭代列表,但会失败RefCell。我什至尝试添加一个向量Ref来保存参考,但仍然无法成功。
如果你删除了,RefCell你可以像这样迭代它:
struct Node {
val: i32,
next: Option<Box<Node>>,
}
fn iterate(node: Option<Box<Node>>) -> Vec<i32> {
let mut result = vec![];
let mut next = node.as_ref().map(|n| &**n);
while let Some(n) = next.take() {
result.push(n.val);
let x = n.next.as_ref().map(|n| &**n);
next = x;
}
result
}
fn main() {
let node = Some(Box::new(Node {
val: 0,
next: Some(Box::new(Node { val: 1, next: None })),
}));
let result = iterate(node);
print!("{:?}", result)
}
Run Code Online (Sandbox Code Playgroud)
也许也可以RefCell,但我无法解决生命周期问题。
| 归档时间: |
|
| 查看次数: |
1222 次 |
| 最近记录: |