RefCell::borrow 是否移动内容?
Does RefCell::borrow move the contents?
我有一个链表类型的结构,使用 Option、Rc 和 RefCell。
我想为它实现 fmt::Debug,但是 运行 进入可爱的 "cannot move out of borrowed content" 错误。
use std::fmt;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Clone, Debug, Ord, Eq, PartialOrd, PartialEq)]
struct NodeId {id: String}
impl NodeId {
pub fn new(s: &str) -> NodeId { NodeId{id: s.to_string()}}
}
struct NodeInfo {
nodeid: NodeId,
prev: Option<Rc<RefCell<NodeInfo>>>,
next: Option<Rc<RefCell<NodeInfo>>>,
}
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {} {} )", self.nodeid.id,
match self.prev { None => "none".to_string(), Some(ref n) => n.borrow().nodeid.id},
match self.next { None => "none".to_string(), Some(ref n) => "some".to_string()},
)
}
}
fn main() {}
理想情况下,调试输出能够显示 .next 和 .previous 节点的 ID。但是 Rust 不允许访问它们。尝试 .borrow() RefCell 的内容导致错误,但我不明白为什么。
在这里玩一下:http://is.gd/Sah7sT
Does RefCell::borrow() move the contents?
没有。叫它借来让它移动是相当卑鄙的! ^_^
问题是您正试图将 id
移出您借用的结构。这是一步,因为 String
不是 Copy
:
n.borrow().nodeid.id
相反,使用 clone
保留当前字符串,return 一个全新的字符串:
n.borrow().nodeid.id.clone()
为了扩展@Shepmaster 的答案(这是绝对正确的),在这种情况下,您可以通过将子节点的 ID 直接写入格式化程序来避免复制字符串。
我选择使用新类型来避免重复:
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {:?} {:?} )", self.nodeid.id, ChildNode(&self.prev), ChildNode(&self.next))
}
}
struct ChildNode<'a>(&'a Option<Rc<RefCell<NodeInfo>>>);
impl<'a> fmt::Debug for ChildNode<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref n) => write!(f, "{}", n.borrow().nodeid.id),
None => write!(f, "None"),
}
}
}
我有一个链表类型的结构,使用 Option、Rc 和 RefCell。
我想为它实现 fmt::Debug,但是 运行 进入可爱的 "cannot move out of borrowed content" 错误。
use std::fmt;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Clone, Debug, Ord, Eq, PartialOrd, PartialEq)]
struct NodeId {id: String}
impl NodeId {
pub fn new(s: &str) -> NodeId { NodeId{id: s.to_string()}}
}
struct NodeInfo {
nodeid: NodeId,
prev: Option<Rc<RefCell<NodeInfo>>>,
next: Option<Rc<RefCell<NodeInfo>>>,
}
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {} {} )", self.nodeid.id,
match self.prev { None => "none".to_string(), Some(ref n) => n.borrow().nodeid.id},
match self.next { None => "none".to_string(), Some(ref n) => "some".to_string()},
)
}
}
fn main() {}
理想情况下,调试输出能够显示 .next 和 .previous 节点的 ID。但是 Rust 不允许访问它们。尝试 .borrow() RefCell 的内容导致错误,但我不明白为什么。
在这里玩一下:http://is.gd/Sah7sT
Does RefCell::borrow() move the contents?
没有。叫它借来让它移动是相当卑鄙的! ^_^
问题是您正试图将 id
移出您借用的结构。这是一步,因为 String
不是 Copy
:
n.borrow().nodeid.id
相反,使用 clone
保留当前字符串,return 一个全新的字符串:
n.borrow().nodeid.id.clone()
为了扩展@Shepmaster 的答案(这是绝对正确的),在这种情况下,您可以通过将子节点的 ID 直接写入格式化程序来避免复制字符串。
我选择使用新类型来避免重复:
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {:?} {:?} )", self.nodeid.id, ChildNode(&self.prev), ChildNode(&self.next))
}
}
struct ChildNode<'a>(&'a Option<Rc<RefCell<NodeInfo>>>);
impl<'a> fmt::Debug for ChildNode<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref n) => write!(f, "{}", n.borrow().nodeid.id),
None => write!(f, "None"),
}
}
}