Rust 谁拥有一个箱子?

Rust 谁拥有一个箱子?,rust,Rust,我现在正在学习生锈。我想检查一下我对rust所有权的理解。我对递归结构中的所有权和借用概念感到困惑。我在中看到了这个代码 //允许引用Cons和Nil而不使用名称空间 使用列表:{Cons,Nil}; //链表节点,可以采用这两种变体中的任何一种 枚举列表{ //缺点:包装元素和指向下一个节点的指针的元组结构 Cons(u32,盒子), //Nil:表示链接列表结束的节点 无 } //方法可以附加到枚举 impl列表{ //创建一个空列表 fn new()->List{ //`Nil`具有类型`

我现在正在学习生锈。我想检查一下我对rust所有权的理解。我对递归结构中的所有权和借用概念感到困惑。我在中看到了这个代码

//允许引用Cons和Nil而不使用名称空间
使用列表:{Cons,Nil};
//链表节点,可以采用这两种变体中的任何一种
枚举列表{
//缺点:包装元素和指向下一个节点的指针的元组结构
Cons(u32,盒子),
//Nil:表示链接列表结束的节点
无
}
//方法可以附加到枚举
impl列表{
//创建一个空列表
fn new()->List{
//`Nil`具有类型`List`
无
}
//使用一个列表,并返回同一个列表,其前面有一个新元素
fn预结束(自身,元素:u32)->列表{
//`Cons`还有类型列表
Cons(元素,方框::新(自身))
}
//返回列表的长度
fn len(&self)->u32{
//必须匹配'self',因为此方法的行为
//取决于“self”的变体`
//`self`具有类型`&List`,`*self`具有类型` List`,在
//具体类型“T”优先于引用“&T”上的匹配`
匹配自我{
//不能拥有尾巴,因为“self”是借来的;
//取而代之的是引用尾部
Cons(u,ref tail)=>1+tail.len(),
//基本情况:空列表的长度为零
零=>0
}
}
//以(堆分配的)字符串形式返回列表的表示形式
fn字符串化(&self)->字符串{
匹配自我{
反面(正面、反面)=>{
//'format!'类似于'print!`,但返回一个堆
//已分配字符串,而不是打印到控制台
格式!(“{},{}”,head,tail.stringify())
},
零=>{
格式!(“无”)
},
}
}
}
fn main(){
//创建一个空的链表
让mut list=list::new();
//附加一些元素
list=list.prepend(1);
list=list.prepend(2);
list=list.prepend(3);
//显示列表的最终状态
println!(“链表的长度:{}”,list.len());
println!(“{}”,list.stringify());
}
如何可视化此代码的堆栈和堆

据我所知,
prepend
拥有列表的所有权,在堆中分配空间,并将列表移动到堆中。当
prepend
完成时,它将新创建的列表移动(赋予所有权)到外部变量

这是正确的吗

第一个列表::新返回Nil,因此堆栈将包含Nil

在list.prepend(1)执行之后,Nil将位于堆的地址0x0000(假设),堆栈将包含Cons(1,0x0000)

在list.prepend(2)之后,执行的Cons(1,0x0000)将位于堆中的地址0x00002(假设),堆栈将包含Cons(2,0x0002)

在list.prepend(3)之后,执行的Cons(2,0x0002)将位于堆中的地址0x00004(假设),堆栈将包含Cons(3,0x0004)

现在,谁拥有Cons(1,0x0000)的所有权?Cons(2,0x0002)是否拥有Cons(1,0x0000)的所有权?堆中的变量是否允许拥有资源的所有权

根据这段代码,我假设堆中的变量可能拥有资源的所有权,所以如果Rust解除分配该变量,它也将解除分配该资源。这是正确的吗

Box
表示堆上某处的
Foo
实例,由
Box
对象管理和拥有

因此,对于列表,其最终值为:

let list=Cons(3,Box::new)(Cons(2,Box::new)(Cons(1,Box::new(Nil '))))
  • list
    拥有一个
    list
    对象,该对象是枚举的
    Cons
    变体,拥有一个值
    3
    u32
    和一个
  • 管理并拥有一个
    列表
    实例:一个
    Cons
    变量,它拥有一个
    2
    值和一个其他
  • 第二个
    管理并拥有一个
    列表
    实例:一个
    Cons
    变量,它拥有一个
    1
    值和一个
  • 最后一个
    管理并拥有一个
    列表
    实例:一个
    Nil
    变量
因此,是的,
的内容可能拥有其他
的内容,当
被销毁时,它将正确销毁其内容,而该内容本身也会正确销毁其内容,直到所属树的底部

// Allow Cons and Nil to be referred to without namespacing
use List::{Cons, Nil};

// A linked list node, which can take on any of these two variants
enum List {
    // Cons: Tuple struct that wraps an element and a pointer to the next node
    Cons(u32, Box<List>),
    // Nil: A node that signifies the end of the linked list
    Nil,
}

// Methods can be attached to an enum
impl List {
    // Create an empty list
    fn new() -> List {
        // `Nil` has type `List`
        Nil
    }

    // Consume a list, and return the same list with a new element at its front
    fn prepend(self, elem: u32) -> List {
        // `Cons` also has type List
        Cons(elem, Box::new(self))
    }

    // Return the length of the list
    fn len(&self) -> u32 {
        // `self` has to be matched, because the behavior of this method
        // depends on the variant of `self`
        // `self` has type `&List`, and `*self` has type `List`, matching on a
        // concrete type `T` is preferred over a match on a reference `&T`
        match *self {
            // Can't take ownership of the tail, because `self` is borrowed;
            // instead take a reference to the tail
            Cons(_, ref tail) => 1 + tail.len(),
            // Base Case: An empty list has zero length
            Nil => 0
        }
    }

    // Return representation of the list as a (heap allocated) string
    fn stringify(&self) -> String {
        match *self {
            Cons(head, ref tail) => {
                // `format!` is similar to `print!`, but returns a heap
                // allocated string instead of printing to the console
                format!("{}, {}", head, tail.stringify())
            },
            Nil => {
                format!("Nil")
            },
        }
    }
}

fn main() {
    // Create an empty linked list
    let mut list = List::new();

    // Append some elements
    list = list.prepend(1);
    list = list.prepend(2);
    list = list.prepend(3);

    // Show the final state of the list
    println!("linked list has length: {}", list.len());
    println!("{}", list.stringify());
}