gpt4 book ai didi

rust - 获取对 Rc 后面对象的引用

转载 作者:行者123 更新时间:2023-11-29 08:14:30 25 4
gpt4 key购买 nike

我正在尝试实现简单的 DOM 结构,但对 rust(或不)内存模型感到困惑。

这是一个简单的例子:

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");
}
}

我不明白如何获取对text 字段的引用,而不是副本。

我只看到两个选择:

  1. 使用 RcString(Rc<RefCell<String>>)而不是原始 String .但它会产生大量样板代码和一些开销。
  2. 实现方法如is_text_equal(&self, text: &String) .但它很丑。

此外,也有可能我做的事情完全错了。

最佳答案

说明

这里的问题是您在 NodeData 中管理某些东西 ( RefCell ) .为了RefCell工作,它不能无限制地给出引用。相反,获取对内部数据的引用的唯一方法是使用作用域保护。来自 RefCell documentation :

fn borrow(&self) -> Ref<T>

而不是返回 &T正如您所期望的那样,一个 Ref被退回。这Ref对象反过来可以通过 deref 为您提供引用- 运算符方法。但返回的引用仅在 Ref 期间有效。对象活着!这样RefCell可以跟踪其所有借用。

可能的解决方案

您可以只返回 Ref对象,用户几乎可以将其用作简单的 &String .但是,这很容易导致用户不小心再次借用而引起 panic 。看看这个:

let text = my_node.text();
println!("the text is {} chars long", text.len());
my_node.set_text("hi".into()); // boom!

问题是 RefCell 的内部值只要 Ref 就被认为是不变地借用的对象是活的。在这种情况下 textRef对象,从而借用内在值(value)。在 set_text你试图可变地借用内在值(value)。


当然你也可以自己实现一些实用函数,正如你已经说过的(2.)。

老实说,我会说你应该重新考虑你的设计。是RefCell真的需要吗?通常情况并非如此。通常RefCells仅用于私有(private)的、隐藏的变量,永远不会暴露给用户。上面提到的问题是不做的原因之一。

当然这个答案不是很令人满意,但我认为没有更好的解决方案。

其他提示

  • A &String引用并不比 &str 更强大引用。所以通常只有&str被使用。 &Vec<T>也是如此(很少使用)和 &[T] .请注意,这仅对不可变引用有效 -- &mut String&mut str强大得多.

关于rust - 获取对 Rc 后面对象的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38105624/

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