rust 循环引用和生存期

xoshrz7s  于 2023-03-30  发布在  其他
关注(0)|答案(1)|浏览(155)

我试图创建一个引用自身的结构体(使用Option<Box<>>)。我可以只使用结构体来编译一些东西,但是当使用容器来编译所有的结构体时,我不能使它编译。
这是我试图创建的结构(改编自真实的例子),它能够创建引用父对象的子对象

pub struct Node<'a> {
    value: u32,
    parent: Option<Box<&'a Node<'a>>>,
}

impl<'a> Node<'a> {
    pub fn new_child(&'a self, value: u32) -> Node<'a> {
        Node {
            value,
            parent: Some(Box::new(&self)),
        }
    }
}

This works。但是,当我尝试使用类似Graph的容器构建这些节点时,构建失败:
Playground example

pub trait Graph {
    type NodeType;
    
    fn new_child(&self, value: u32) -> Self::NodeType;
}

struct GraphImpl<'a> {
    root: Node<'a>,
}

impl<'a> Graph for GraphImpl<'a> {
    type NodeType = Node<'a>;
    
    fn new_child(&self, value: u32) -> Self::NodeType {
        self.root.new_child(value)
    }
}

错误:

Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/main.rs:32:9
   |
28 | impl<'a> Graph for GraphImpl<'a> {
   |      -- lifetime `'a` defined here
...
31 |     fn new_child(&self, value: u32) -> Self::NodeType {
   |                  - let's call the lifetime of this reference `'1`
32 |         self.root.new_child(value)
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1`

error: could not compile `playground` due to previous error

我尝试在许多不同的地方添加不同的生命周期标记,但都没有成功。我阅读了不同的问题和答案,很明显我错过了一些东西(我不明白Rust中的生命周期是如何工作的:我真的很感激这里的一些帮助......和一些指针,这样我就可以理解为什么它的工作(或它不应该工作)。
谢谢!

c9qzyr3d

c9qzyr3d1#

你可以通过Graph trait转发生命周期来完成这个任务:

pub trait Graph<'a> {
    type NodeType;
    
    fn new_child(&'a self, value: u32) -> Self::NodeType;
}

struct GraphImpl<'a> {
    root: Node<'a>,
}

impl<'a> Graph<'a> for GraphImpl<'a> {
    type NodeType = Node<'a>;
    
    fn new_child(&'a self, value: u32) -> Self::NodeType {
        self.root.new_child(value)
    }
}

这种自引用的方法在rust中是非常不规范的,我担心它不能很好地扩展到更大的例子。从索引到存储在平面向量中的节点构建图要简单得多,并且完全避免这种情况。

相关问题