如何在没有克隆的情况下更改对拥有值的引用?

约旦

我正在练习阅读《书》时学到的Rust概念。我已经能够List通过复制Box并将其分配list给复制的框来遍历我的枚举,但是直觉,我觉得必须有一种方法只是“使其指向行中的下一个指针”。

如果我尝试不使用bx.clone(),就像这样:self.list = **bx,我将得到“无法从**bx可变引用后面移出”。这意味着我需要拥有它,但是我不能拥有bx它,因为在取消引用它时需要将其作为参考进行移动if let

是否可以或建议在不复制参考的情况下移动参考?

#[derive(Clone)]
enum List {
    Cons(u32, Box<List>),
    Nil,
}
struct ListHolder {
    list: List,
}

impl Iterator for ListHolder {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        if let Cons(num, bx) = &mut self.list {
            let val = *num;
            self.list = *bx.clone(); // This is the key line
            Some(val)
        } else {
            None
        }
    }
}

use List::*;

fn main() {
    let list_inst = ListHolder {
        list: Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))),
    };
    for i in list_inst.into_iter() {
        println!("{}", i); // Prints 1, 2, 3 as expected
    }
}
无伴奏合唱

我认为您的心理模型的关键问题是您只是将其Box<T>视为指针。Rust引用(以及大多数智能指针,如Box<T>)不仅是指针,而且是有效的指针。也就是说,没有空引用,并且引用必须始终始终指向有效数据。

当我们尝试这样做时self.list = **bx;,我们会将数据从bx移到self.list但是,bx并不拥有其数据。当可变借贷bx结束时,实际所有者将持有无效数据。

那么我们该怎么办?最简单的方法是有时称为Jones'Trick的方法,在该方法中,我们将数据切换出bx一些虚拟值。现在,数据中的实际所有者bx将不会保存无效数据。那么我们该怎么做呢?这是该函数的功能范围,该函数std::mem::replace接受一个可变引用和一个值,并用该值替换该可变引用后面的数据,并返回该可变引用后面的内容(包括所有权!)。这正是我们想要在此处执行的操作self.list = std::mem::replace(&mut **bx, List::Nil)再次,List::Nil只是一些伪数据;任何List都将完全相同。

enum List {
    Cons(u32, Box<List>),
    Nil,
}
struct ListHolder {
    list: List,
}

impl Iterator for ListHolder {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        if let Cons(num, bx) = &mut self.list {
            let val = *num;
            self.list = std::mem::replace(&mut **bx, List::Nil); // This is the key line
            Some(val)
        } else {
            None
        }
    }
}

use List::*;

fn main() {
    let list_inst = ListHolder {
        list: Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))),
    };
    for i in list_inst.into_iter() {
        println!("{}", i); // Prints 1, 2, 3 as expected
    }
}

(操场)

为了更加惯用,&mut **bx我们可以简单地使用bx.as_mut()来从框中获取可变的引用,而不是另外,由于已经实现,因此不需要进行into_iter调用,因此不需要将其转换为一个。你也可以想知道,为什么我们仍然必须为一个临时变量。list_instListHolderIteratornumval

原因是该值仍只是参考,我们没有所有者(self.list的所有权这意味着我们必须复制它以返回。u32实现,Copy所以这并不是一个真正的问题,但是,如果您尝试使链表在其元素的类型中具有通用性,则根本行不通。let val = *num;与我们以前无法做到的“移出借用内容”相同。

解决方案是std::mem::replace不仅要获取背后数据的所有权bx,还要获得整个列表的所有权因此,如果我们std::mem::replace(&mut self.list, List::Nil)在销毁之前使用self.list将被替换为虚拟值,并且我们将拥有实际列表的所有权,包括值和列表尾部。这也意味着我们可以拥有self.list = *bx,就像我确定您最初想要的那样。

impl Iterator for ListHolder {
    type Item = u32;
    fn next(&mut self) -> Option<u32> {
        if let Cons(num, bx) = std::mem::replace(&mut self.list, List::Nil) {
            self.list = *bx;
            Some(num)
        } else {
            None
        }
    }
}

(操场)

现在的结果是,您几乎可以毫不费力地使列表通用

如果您想了解更多有关Rust的所有权模型如何影响链表实现的信息,您将无法比学习优秀的Rust系列文章中的链表更好该系列详细介绍了这里的所有内容以及许多变体。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在不更改现有json数组值的情况下克隆json数组

来自分类Dev

在Vue JS watcher中如何在没有无限循环的情况下更改对象的属性?

来自分类Dev

如何在IE11中没有引用的情况下克隆jQuery对象及其子对象

来自分类Dev

Rust如何在没有重载函数的情况下拥有泛型?

来自分类Dev

如何在没有重点的情况下拥有关闭程序的钥匙

来自分类Dev

我如何在没有sudo的情况下删除根拥有的文件

来自分类Dev

如何在没有自动挂载的情况下拥有 sshfs 磁盘?

来自分类Dev

如何在没有填充的情况下更改Excel中单元格的值

来自分类Dev

SQL-如何在没有多个子选择的情况下比较更改的列值

来自分类Dev

在没有队列的情况下,如何在多处理中更改类的值?

来自分类Dev

如何在 Angular 中没有错误值的情况下更改标签的输入?

来自分类Dev

如何在没有触发事件的情况下更改select2的值?

来自分类Dev

如何在没有上下文的情况下访问“克隆站点对象”?

来自分类Dev

如何在没有参考的情况下克隆通用List <T>?

来自分类Dev

如何在没有克隆的情况下从github删除非活动分支?

来自分类Dev

如何在没有子节点的情况下克隆Kinetic.node?

来自分类Dev

如何在没有中断常量的情况下返回可引用的引用类型?

来自分类Dev

克隆/灵巧性-在某种情况下,如何更改仅所有者拥有查看权限的内容类型对象的所有权角色?

来自分类Dev

如何在没有绝对路径的情况下引用打字稿文件?

来自分类Dev

如何在没有'uses'b的情况下从多个文件引用常量?

来自分类Dev

如何在没有类名的情况下引用全局静态字典?

来自分类Dev

如何在没有完整路径的情况下从git status快速引用文件

来自分类Dev

如何在没有脚本块的情况下引用整个管道对象

来自分类Dev

如何在没有明确引用的情况下访问打开的DbContext?

来自分类Dev

如何在没有给定示例的任何引用的情况下获取Sql Record

来自分类Dev

如何在没有变量的情况下使用 React.js 引用?

来自分类Dev

如何在没有引用的情况下创建静态类对象?

来自分类Dev

是否可以在不更改对现有导航属性的所有引用的情况下促进与实体的多对多关系?

来自分类常见问题

没有VPC的情况下如何拥有默认安全组?

Related 相关文章

  1. 1

    如何在不更改现有json数组值的情况下克隆json数组

  2. 2

    在Vue JS watcher中如何在没有无限循环的情况下更改对象的属性?

  3. 3

    如何在IE11中没有引用的情况下克隆jQuery对象及其子对象

  4. 4

    Rust如何在没有重载函数的情况下拥有泛型?

  5. 5

    如何在没有重点的情况下拥有关闭程序的钥匙

  6. 6

    我如何在没有sudo的情况下删除根拥有的文件

  7. 7

    如何在没有自动挂载的情况下拥有 sshfs 磁盘?

  8. 8

    如何在没有填充的情况下更改Excel中单元格的值

  9. 9

    SQL-如何在没有多个子选择的情况下比较更改的列值

  10. 10

    在没有队列的情况下,如何在多处理中更改类的值?

  11. 11

    如何在 Angular 中没有错误值的情况下更改标签的输入?

  12. 12

    如何在没有触发事件的情况下更改select2的值?

  13. 13

    如何在没有上下文的情况下访问“克隆站点对象”?

  14. 14

    如何在没有参考的情况下克隆通用List <T>?

  15. 15

    如何在没有克隆的情况下从github删除非活动分支?

  16. 16

    如何在没有子节点的情况下克隆Kinetic.node?

  17. 17

    如何在没有中断常量的情况下返回可引用的引用类型?

  18. 18

    克隆/灵巧性-在某种情况下,如何更改仅所有者拥有查看权限的内容类型对象的所有权角色?

  19. 19

    如何在没有绝对路径的情况下引用打字稿文件?

  20. 20

    如何在没有'uses'b的情况下从多个文件引用常量?

  21. 21

    如何在没有类名的情况下引用全局静态字典?

  22. 22

    如何在没有完整路径的情况下从git status快速引用文件

  23. 23

    如何在没有脚本块的情况下引用整个管道对象

  24. 24

    如何在没有明确引用的情况下访问打开的DbContext?

  25. 25

    如何在没有给定示例的任何引用的情况下获取Sql Record

  26. 26

    如何在没有变量的情况下使用 React.js 引用?

  27. 27

    如何在没有引用的情况下创建静态类对象?

  28. 28

    是否可以在不更改对现有导航属性的所有引用的情况下促进与实体的多对多关系?

  29. 29

    没有VPC的情况下如何拥有默认安全组?

热门标签

归档