pattern-matching - 为什么这个结构在模式匹配后没有 move ?

标签 pattern-matching rust move

基于 Preventing move semantics during pattern matching ,我的理解是,当我对结构执行 match 时,如果不使用引用来进行匹配,则该结构将被 move ,因为它不是原始类型。为了对此进行测试,我实现了以下内容:

struct Point {
    x: i32,
    y: i32,
}

let origin = Point { x: 0, y: 0 };

match origin {
    Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
}

// to check if the origin has been moved, and it seems not, why ?? 
match origin {
    Point { x: x1, y: y1 } => println!("({},{})", x1, y1),
}

输出是(0,0) (0,0),这意味着原始结构仍然存在。它不应该在第一次 匹配 之后 move 吗?

最佳答案

重要的不是匹配值的类型,而是每个匹配臂上绑定(bind)的每个值的类型。

在您的结构 Point 中,字段 xy 的类型为 i32。这个类型实现了Copy,所以 Rust 会复制这个类型的值而不是 move 它们——这意味着原始值仍然被认为是有效的。由于匹配臂上绑定(bind)的所有值都实现了 Copy,因此没有必要使 origin 无效。字段访问的工作方式类似:当 origin.x 实现 Copy 时,origin.x 不会使 origin 无效!

现在,如果字段的类型没有实现Copy(例如,String),那就另当别论了。 Rust 被迫将每个 String 从字段 move 到匹配臂中的绑定(bind)。结果,origin 中的字段无效。由于我们不能使用具有无效字段的值,因此整个结构也将无效。

让我们来点有趣的东西。考虑以下代码:

struct Point {
    x: i32,
    y: String,
}

let origin = Point { x: 0, y: "zero".to_string() };

match origin {
    Point { x: x1, y: _ } => println!("({},...)", x1),
}

match origin {
    Point { x: x1, y: _ } => println!("({},...)", x1),
}

match origin {
    Point { x: _, y: y1 } => println!("(...,{})", y1),
}

match origin {
    Point { x: _, y: y1 } => println!("(...,{})", y1),
}

在这里,我们使用占位符模式 (_) 表示我们对某个字段的值不感兴趣。我们还可以使用通配符模式(..,如 Point { x: x1, .. })来忽略所有未在结构模式中命名的字段.在任何一种情况下,它都具有不 move 被忽略的字段的效果。

在前两次匹配中,我们只绑定(bind)了x字段,它的类型是i32。由于 i32 实现了 Copy,因此 origin 不会失效,即使 originorigin.y 是可复制的(origin.y 只是停留在原处)。

在第三个匹配中,我们只绑定(bind)y字段,它是String类型。由于 String 没有实现 Copyorigin.y 被 move 到 y1 中,所以 origin 无效。这会导致第四次匹配出现编译器错误,因为它在 origin 无效后尝试使用它:

error[E0382]: use of partially moved value: `origin`
  --> <anon>:21:11
   |
18 |         Point { x: _, y: y1 } => println!("(...,{})", y1),
   |                          -- value moved here
...
21 |     match origin {
   |           ^^^^^^ value used here after move
   |
   = note: move occurs because `origin.y` has type `std::string::String`, which does not implement the `Copy` trait

error[E0382]: use of moved value: `origin.y`
  --> <anon>:22:26
   |
18 |         Point { x: _, y: y1 } => println!("(...,{})", y1),
   |                          -- value moved here
...
22 |         Point { x: _, y: y1 } => println!("(...,{})", y1),
   |                          ^^ value used here after move
   |
   = note: move occurs because `origin.y` has type `std::string::String`, which does not implement the `Copy` trait

关于pattern-matching - 为什么这个结构在模式匹配后没有 move ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40353047/

相关文章:

java - Java中的形状模式匹配算法

rust - 对于 "big"结构,只使用引用是最惯用/最有效的吗?

inheritance - 在 Rust 1.3 中继承结构的最佳方式是什么?

linux - 绑定(bind)() : "Cannot assign request address"

javascript - jquery, mouseenter 下移图片

html - move 图像

c++ - move 赋值运算符 C++

functional-programming - 函数式语言中的 'Pattern Matching' 是什么?

sql - Limited, Ltd, Incorporated, Inc 等的字符串模式匹配

haskell - 检查字符串是否由平衡括号组成