为什么在取消引用非元组时,对取消引用的引用元组的匹配不起作用?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在取消引用非元组时,对取消引用的引用元组的匹配不起作用?相关的知识,希望对你有一定的参考价值。

我正在尝试对Vec的枚举进行排序。请忽略排序机制本身,这只是一个简化的例子。

use std::cmp::Ordering;

enum MyEnum {
    Option1,
    Option2,
}

fn main() {
    let mut my_list: Vec<MyEnum> = vec![MyEnum::Option1, MyEnum::Option2, MyEnum::Option1];

    // (1) - doesn't work
    my_list.sort_unstable_by(|a, b| match (*a, *b) {
        (MyEnum::Option1, MyEnum::Option1) => Ordering::Equal,
        (MyEnum::Option1, MyEnum::Option2) => Ordering::Less,
        _  => Ordering::Greater
    });
}

我收到以下错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:12:44
   |
12 |     my_list.sort_unstable_by(|a, b| match (*a, *b) {
   |                                            ^^ cannot move out of borrowed content

以下两种变体有效:

// (2)
my_list.sort_unstable_by(|a, _b| match *a {
    MyEnum::Option1 => Ordering::Less,
    MyEnum::Option2 => Ordering::Greater
});

// (3)
my_list.sort_unstable_by(|a, b| match (a, b) {
    (&MyEnum::Option1, &MyEnum::Option1) => Ordering::Equal,
    (&MyEnum::Option1, &MyEnum::Option2) => Ordering::Less,
    _  => Ordering::Greater
});

当我想匹配一个简单的引用时,我可以取消引用它(变体2);为什么这在变体1中的元组中不起作用?

我理解为什么3个有效,但是要理解1中的移动究竟发生在哪里以及如何以不同的方式进行。

答案

确切的移动发生在哪里

移动发生在编译器指向的位置 - *a。您正在将a的内容转移到一个全新的元组中。你不能这样做,所以编译器会给出错误。

在没有真正解除引用的情况下“解除引用”匹配变量的能力是编译器提供的一些语法上的好处,但它非常有限。它没有“看到”表达式,它只查看一些选择语法结构并知道忽略它们。

编译器可能会被增强以查看这些情况,但可能在此时成本/收益权衡是不利的。

也可以看看:

以上是关于为什么在取消引用非元组时,对取消引用的引用元组的匹配不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

将对元组的引用的迭代器解压缩为两个引用集合

流畅的python第八章对象引用,可变性和垃圾回收

无法使用 Pig 中的 Elephant Bird 访问带有包和元组的嵌套 JSON

为啥取消引用称为取消引用的指针?

怎么取消循环引用警告

为啥要使用 void 指针来取消引用数据类型的变量?