Rust 理解枚举的移动语义
所以我在看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并不绑定任何东西。从 与标识符模式不同,它不复制、移动或借用匹配的值Rust 理解枚举的移动语义,rust,move,Rust,Move,所以我在看impl for is_some for选项,我注意到它在引擎盖下使用match*self{},所以它在内部移动它 我的问题是,如果它被移动,我怎么能做这样的事情 我的期望是,我应该只能调用一次is_some,下次调用它时,我应该会收到某种错误,说它被移动了……但不,它编译得很好 我误解了什么?*self-in-match*self{…}不会移动或复制self指向的内容。从我的 根据scrutinee表达式是位置表达式还是值表达式,匹配的行为会有所不同。如果scrutinee表达式是值
其中通配符模式的含义参见@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