Rust 获取对Rc后面的对象的引用
我试图实现简单的DOM结构,但却被锈迹(或非锈迹)内存模型弄糊涂了 下面是一个简单的例子:Rust 获取对Rc后面的对象的引用,rust,Rust,我试图实现简单的DOM结构,但却被锈迹(或非锈迹)内存模型弄糊涂了 下面是一个简单的例子: struct NodeData { text: String, } struct Node(Rc<RefCell<NodeData>>); impl Node { fn new() -> Node { Node(Rc::new(RefCell::new(NodeData { text: String::new()
struct NodeData {
text: String,
}
struct Node(Rc<RefCell<NodeData>>);
impl Node {
fn new() -> Node {
Node(Rc::new(RefCell::new(NodeData {
text: String::new()
})))
}
fn set_text(&self, text: String) {
self.0.borrow_mut().text = text;
}
// it works, but has unneeded, expensive clone
// pub fn text(&self) -> String {
// self.0.borrow().text.clone()
// }
pub fn text(&self) -> &String {
// ???
}
}
fn main() {
let node = Node::new();
node.set_text("text".to_string());
if node.text() == "text" {
println!("equal");
}
}
struct NodeData{
文本:字符串,
}
结构节点(Rc);
impl节点{
fn new()->节点{
节点(Rc::new(RefCell::new)(NodeData{
text:String::new()
})))
}
fn set_text(&self,text:String){
self.0.borrow_mut().text=text;
}
//它可以工作,但有不必要的昂贵克隆
//发布fn文本(&self)->字符串{
//self.0.borrow().text.clone()
// }
发布fn文本(&self)->字符串(&S){
// ???
}
}
fn main(){
让node=node::new();
node.set_text(“text.to_string());
如果node.text()=“文本”{
println!(“相等”);
}
}
我不明白如何获取文本字段的引用,不是它的副本
我只看到两种选择:
RcString(Rc)
代替原始String
。但它会产生大量样板代码和一些开销这样的实现方法是\u text\u equal(&self,text:&String)
。但是很难看RefCell
中管理某些内容(NodeData
)。为了使RefCell
工作,它不能无限制地给出引用。相反,获取对内部数据的引用的唯一方法是使用范围保护。从:
问题是只要Ref
对象处于活动状态,Ref单元格的内部值就被认为是不可变的借用。在本例中,text
是一个Ref
对象,因此借用了内部值。在set_text
中,您尝试可变地借用内部值
当然,您也可以自己实现一些实用功能,正如您已经说过的(2)
老实说,我想说你应该重新考虑你的设计。是否真的需要RefCell
?通常情况并非如此。通常,RefCells
仅用于私有隐藏变量,从不向用户公开。上述问题是不这样做的原因之一
当然,这个答案不是很令人满意,但我认为没有更好的解决办法
附加提示
&String
引用并不比&str
引用更强大。因此通常只使用&str
。这同样适用于&Vec
(很少使用)和&T]
。请注意,这仅对不可变引用有效--&mut String
比&mut str
强大得多
感谢您的详细解释,但据我所知,我应该返回Ref
,而不是Ref
,这是我需要的。NodeData必须是私有的。关于设计-我不知道。我试图实现简单的DOM结构,而不是不安全的,只使用现有的方法/结构,而不是从头开始创建一切。而RefCell
是我找到的实现可变数据的唯一方法。@RazrFalcon使用map
函数只获取文本:Ref::map(self.0.borrow(),|n |&n.text)
@Arjan谢谢!这正是我想要的。我当前使用Rc的实现之间唯一的区别是我需要两种方法:regular和_mut。据我所知,Ref::map没有性能成本,因为它只是一个包装器,对吗?
fn borrow(&self) -> Ref<T>
let text = my_node.text();
println!("the text is {} chars long", text.len());
my_node.set_text("hi".into()); // boom!