如何在不切片的情况下解构向量?

Pet*_*rne 9 vector pattern-matching destructuring slice rust

我可以通过获取向量的切片和对元组中项目的引用来解构元组向量:

let items = vec![("Peter".to_string(), 180)];

if let [(ref name, ref age)] = items.as_slice() {
    println!("{} scored {}", name, age);
};
Run Code Online (Sandbox Code Playgroud)

如何直接解构向量,将项目移出元组。像这样的东西:

let items = vec![("Peter".to_string(), 180)];

if let [(name, age)] = items {
    println!("{} scored {}", name, age);
};
Run Code Online (Sandbox Code Playgroud)

编译上述结果导致错误:

let items = vec![("Peter".to_string(), 180)];

if let [(ref name, ref age)] = items.as_slice() {
    println!("{} scored {}", name, age);
};
Run Code Online (Sandbox Code Playgroud)

She*_*ter 6

你同时问两个不相交的问题:

  1. 如何移出向量?
  2. 如何解构物品?

第二个很简单:

let item = ("Peter".to_string(), 180);
let (name, score) = item;
Run Code Online (Sandbox Code Playgroud)

您不需要if let语法,因为这种模式匹配不会失败。当然,item解构后不能使用,因为你已经将所有权itemtoname转移了score

第一个问题比较难,并且涉及到 Rust 的核心部分。如果您将所有权从向量中转移出来,那么向量处于什么状态?在 C 中,您将有一些未定义的内存块位于向量中,等待分解您的程序。假设你调用free了那个字符串,那么当你在向量中使用指向同一个字符串的东西时会发生什么?

有几种方法可以解决它...

向量继续拥有这些项目

let items = vec![("Peter".to_string(), 180)];

if let Some((name, score)) = items.first() {
    println!("{} scored {}", name, score);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们抓住一个参考的第一个项目,然后引用的名称和得分。由于向量可能没有任何项目,它返回一个Option,所以我们确实使用if let。编译器不会让我们在向量生命周期内使用这些项目。

从向量中转移一个元素的所有权

let mut items = vec![("Peter".to_string(), 180)];

let (name, score) = items.remove(0); // Potential panic!
println!("{} scored {}", name, score);
Run Code Online (Sandbox Code Playgroud)

在这里,我们remove是数组中的第一项。vector 不再拥有它,我们可以用它做任何我们想做的事情。我们立即对其进行解构。itemsname并且score都有独立的生命周期。

从向量转移所有元素所有权

let items = vec![("Peter".to_string(), 180)];

for (name, score) in items {
    println!("{} scored {}", name, score);
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们消耗了向量,因此它在for循环后不再可用。的所有权namescore在环路中结合被转移到的变量。

克隆项目

let items = vec![("Peter".to_string(), 180)];

let (name, score) = items[0].clone(); // Potential panic!
println!("{} scored {}", name, score);
Run Code Online (Sandbox Code Playgroud)

在这里,我们制作了向量中项目的版本。我们拥有新项目,向量拥有原始项目。

  • @PeterHorne:不过,您现在大大高估了 Rust 类型系统。部分移动仅适用于未实现 `Drop` 特征的结构(参见 http://is.gd/tRTWDR => *不能移出定义了 `Drop` 特征的 `Person` 类型*),因为这样编译器就无法知道 `Drop` trait 将依赖什么。 (2认同)