Rust 理解枚举的移动语义

Rust 理解枚举的移动语义,rust,move,Rust,Move,所以我在看impl for is_some for选项,我注意到它在引擎盖下使用match*self{},所以它在内部移动它 我的问题是,如果它被移动,我怎么能做这样的事情 我的期望是,我应该只能调用一次is_some,下次调用它时,我应该会收到某种错误,说它被移动了……但不,它编译得很好 我误解了什么?*self-in-match*self{…}不会移动或复制self指向的内容。从我的 根据scrutinee表达式是位置表达式还是值表达式,匹配的行为会有所不同。如果scrutinee表达式是值

所以我在看impl for is_some for选项,我注意到它在引擎盖下使用match*self{},所以它在内部移动它

我的问题是,如果它被移动,我怎么能做这样的事情

我的期望是,我应该只能调用一次is_some,下次调用它时,我应该会收到某种错误,说它被移动了……但不,它编译得很好

我误解了什么?

*self-in-match*self{…}不会移动或复制self指向的内容。从我的

根据scrutinee表达式是位置表达式还是值表达式,匹配的行为会有所不同。如果scrutinee表达式是值表达式,则首先将其计算到临时位置

当scrutinee表达式是位置表达式时,匹配不会分配临时位置;但是,按值绑定可能会从内存位置复制或移动

*自我是一种场所表达。从我的

表达式分为两大类:位置表达式和值表达式

位置表达式是表示内存位置的表达式。这些表达式是指向局部变量、静态变量、解引用*expr、数组索引表达式expr[expr]、字段引用expr.f和括号内的位置表达式的路径。所有其他表达式都是值表达式

值表达式是表示实际值的表达式

您可能还想知道match主体中的Some_=>true arm并不绑定任何东西。从

与标识符模式不同,它不复制、移动或借用匹配的值

其中它表示通配符模式u.

*self-in-match*self{…}不会移动或复制self指向的内容。从我的

根据scrutinee表达式是位置表达式还是值表达式,匹配的行为会有所不同。如果scrutinee表达式是值表达式,则首先将其计算到临时位置

当scrutinee表达式是位置表达式时,匹配不会分配临时位置;但是,按值绑定可能会从内存位置复制或移动

*自我是一种场所表达。从我的

表达式分为两大类:位置表达式和值表达式

位置表达式是表示内存位置的表达式。这些表达式是指向局部变量、静态变量、解引用*expr、数组索引表达式expr[expr]、字段引用expr.f和括号内的位置表达式的路径。所有其他表达式都是值表达式

值表达式是表示实际值的表达式

您可能还想知道match主体中的Some_=>true arm并不绑定任何东西。从

与标识符模式不同,它不复制、移动或借用匹配的值


其中通配符模式的含义参见@dkim的答案,以获得更正式和引用的答案

如果函数的签名通过引用接受,则它不会获得值的所有权。Option.is_是一些实际需要的&self而不是self

有趣的部分是当self:Copy没有绑定时,如何允许在接收&self的函数中使用*self

为了测试这一点,让我们创建一个包含类似内容的最小示例:

这很好。但是,让我们将A::X_u模式更改为A::X_uS:

这无法编译:

error[E0507]: cannot move out of `a.0` which is behind a shared reference
 --> src/lib.rs:7:11
  |
7 |     match *a {
  |           ^^ help: consider borrowing here: `&*a`
8 |         A::X(_s) => {
  |              --
  |              |
  |              data moved here
  |              move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
因此,只要不用于移动内部非复制值,解除对非复制枚举的引用就完全可以了很好,因为它保证永远不会使用基础值,而_s不会编译,因为它只是一个正常的allowunused变量


这也是有意义的,因为它允许同一匹配臂在复制和非复制类型上工作,只要使用不违反所有权规则

如果函数的签名通过引用接受,则它不会获得值的所有权。Option.is_是一些实际需要的&self而不是self

有趣的部分是当self:Copy没有绑定时,如何允许在接收&self的函数中使用*self

为了测试这一点,让我们创建一个包含类似内容的最小示例:

这很好。但是,让我们将A::X_u模式更改为A::X_uS:

这无法编译:

error[E0507]: cannot move out of `a.0` which is behind a shared reference
 --> src/lib.rs:7:11
  |
7 |     match *a {
  |           ^^ help: consider borrowing here: `&*a`
8 |         A::X(_s) => {
  |              --
  |              |
  |              data moved here
  |              move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
因此,只要不用于移动内部非复制值,解除对非复制枚举的引用就完全可以了很好,因为它保证永远不会使用基础值,而_s不会编译,因为它只是一个正常的allowunused变量 可悲的


这也是有意义的,因为它允许相同的匹配臂在复制和非复制类型上工作,只要没有使用违反了所有权规则

是否有按值自取?另一个要考虑的是,有一个IMPL副本供选择:T:拷贝和整数原语都是复制的。因此,选项也是复制的。IsthOutsIn自己取值吗?另一个要考虑的是,有一个IMPL拷贝的选项,其中T:拷贝和整数原语都是拷贝。因此,选项也是复制。
#[derive(Debug)]
pub enum A {
    X(String),
    Y(i32),
}
pub fn f(a: &A) {
    match *a {
        A::X(_s) => {
            //  dbg!(s);
        }
        A::Y(_i) => {
            //  dbg!(i);
        }
    };
}
error[E0507]: cannot move out of `a.0` which is behind a shared reference
 --> src/lib.rs:7:11
  |
7 |     match *a {
  |           ^^ help: consider borrowing here: `&*a`
8 |         A::X(_s) => {
  |              --
  |              |
  |              data moved here
  |              move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait