rust - 存储对自身的引用

标签 rust weak-references

我正在尝试在 Rust 中创建一个节点网络,我希望网络中的每个节点都知道所有其他连接的节点。我认为这可以通过弱 Rc 来完成,如下所示:

use std::cell::Cell;
use std::cell::RefCell;
use std::rc::Rc;
use std::rc::Weak;

struct Node {
    name: String,
    known_nodes: Rc<RefCell<Vec<Weak<Node>>>>,
}

impl Node {
    fn connect_to_network(&mut self) {
        self.known_nodes
            .borrow_mut()
            .push(Rc::downgrade(&Rc::new(*self)));
    }
}

fn main() {
    let known_nodes = Rc::new(RefCell::new(Vec::new()));
    let node_one = Node {
        name: "node1",
        known_nodes: known_nodes.copy(),
    };
    node_one.connect_to_network();
    let node_two = Node {
        name: "node2",
        known_nodes: known_nodes.copy(),
    };
    node_two.connect_to_network();
}

然而这产生了

cannot move out of borrowed content

在:

self.known_senders.borrow_mut().push(Rc::downgrade(&Rc::new(*self)));

因为 *self 被移出了 &Rc::new(*self) 中的借用内容。 关于每个节点如何跟踪网络中所有其他节点的任何想法?

最佳答案

你应该将你的节点和你的网络分开,因为你的网络必须拥有你的节点的所有权来创建一个Rc(或者至少,它必须已经创建了 Rc)。这是一个更好的设计,可以实现您想要的:

use std::rc::Rc;
use std::rc::Weak;
use std::cell::RefCell;

#[derive(Debug)]
struct Node {
    name: String,
}

#[derive(Default, Debug)]
struct Network {
    nodes: Rc<RefCell<Vec<Weak<Node>>>>,
}

impl Network {
    fn add_node(&mut self, node: Node) -> Rc<Node> {
        let node = Rc::new(node);
        self.nodes.borrow_mut().push(Rc::downgrade(&node));

        node
    }
}

fn main() {
    let mut network = Network::default();
    let node_1 = Node { name: "node_1".into() };
    let node_2 = Node { name: "node_2".into() };

    let _node_1 = network.add_node(node_1);
    let _node_2 = network.add_node(node_2);
}

如果你想存储对self的引用,你可以这样做:

use std::cell::RefCell;
use std::rc::Rc;
use std::rc::Weak;

type MutableNode = Rc<RefCell<Node>>;
type Network = Rc<RefCell<Vec<Weak<RefCell<Node>>>>>;

struct Node {
    name: String,
    others: Network,
}

impl Node {
    fn new(name: String) -> MutableNode {
        let node = Rc::new(RefCell::new(Node {
            name,
            others: Rc::new(RefCell::new(Vec::new())),
        }));
        {
            let tmp = node.borrow();
            tmp.others.borrow_mut().push(Rc::downgrade(&node));
        }

        node
    }

    fn add_node(&mut self, name: String) -> MutableNode {
        let others = self.others.clone();
        let node = Rc::new(RefCell::new(Node { name, others }));
        self.others
            .borrow_mut()
            .push(Rc::downgrade(&node));

        node
    }

    fn len(&self) -> usize {
        self.others.borrow().len()
    }
}

fn main() {
    let node_0 = Node::new("node_0".into());
    let node_1 = node_0.borrow_mut().add_node("node_1".into());
    let node_2 = node_0.borrow_mut().add_node("node_2".into());

    assert_eq!(node_0.borrow().len(), 3);
    assert_eq!(node_1.borrow().len(), 3);
    assert_eq!(node_2.borrow().len(), 3);
}

关于rust - 存储对自身的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50677344/

相关文章:

rust - 涉及关联类型的不满足特征界限

rust - 使用 trim_end_matches 作为闭包函数 : expected signature . 类型不匹配 .. 找到 "for<' r> 的签名 ..."

java - 如何避免回调中的内存泄漏?

java - 具有弱引用的 ConcurrentHashmap

java - 对字符串和字符串常量的弱引用

javascript - 为什么 for 循环中声明的变量的最后一次迭代没有被垃圾收集?

java - 如何避免 Android 中的 OutOfMemoryError

rust - 如何将引用返回到 Rc<RefCell<>> 函数参数?

rust - 我可以使用 Deref<Target = Other> 从 Other 继承特征实现吗?

macros - 如何在宏中添加前缀/后缀标识符?