解构向量(不需要切片)

时间:2015-03-28 11:28:20

标签: rust

我可以通过获取一个向量片段并引用元组中的项目来构造元组向量:

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

if let [(ref name, ref age)] = items.as_ref() {
    println!("{} scored {}", name, age);
};

如何直接对矢量进行解构,将项目移出元组。像这样:

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

if let [(name, age)] = items {
    println!("{} scored {}", name, age);
};

在错误中编译上述结果:

src/main.rs:6:12: 6:25 error: mismatched types:
 expected `collections::vec::Vec<(collections::string::String, _)>`,
    found `&[_]`
(expected struct `collections::vec::Vec`,
    found &-ptr) [E0308]
src/main.rs:6     if let [(name, age)] = items {
                         ^~~~~~~~~~~~~

2 个答案:

答案 0 :(得分:2)

你不能这样做,the definition of Vec in std

pub struct Vec<T> {
    ptr: Unique<T>,
    len: usize,
    cap: usize,
}

所以你不能直接匹配它,只有:

match xs {
    Vec { ptr: x, .. } => {...}
} 

error: field `ptr` of struct `collections::vec::Vec` is private

答案 1 :(得分:2)

你一次要问两个不相交的问题:

  1. 如何移出矢量?
  2. 如何解构项目?
  3. 第二个很简单:

    let item = ("Peter".to_string(), 180);
    let (name, score) = item;
    

    您不需要if let语法,因为此模式匹配无法失败。当然,您可以在对其进行解构后使用item,因为您已将从item转移到namescore }。

    第一个问题更难,并且成为Rust的核心部分。如果您从一个向量转移所有权,那么 中的向量是什么状态?在C中,你会在向量中有一些未定义的内存块,等待将程序分开。假设您在该字符串上调用了free,那么当您在向量中使用指向同一字符串的东西时会发生什么?

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

    向量继续拥有项目

    let items = vec![("Peter".to_string(), 180)];
    
    if let Some(&(ref name, ref score)) = items.first() {
        println!("{} scored {}", name, score);
    }
    

    在这里,我们抓住第一项的引用,然后引用名称和分数。由于向量可能没有任何项目,因此会返回Option,因此我们会使用if let。编译器不会让我们使用这些项目的时间长于矢量。

    从矢量

    传输一个元素的所有权
    let mut items = vec![("Peter".to_string(), 180)];
    
    let (name, score) = items.remove(0); // Potential panic!
    println!("{} scored {}", name, score);
    

    在这里,我们remove数组中的第一项。向量不再拥有它,我们可以随心所欲地做任何事情。我们立即解构它。 itemsnamescore都将拥有独立的生命周期。

    从向量

    传输所有元素所有权
    let items = vec![("Peter".to_string(), 180)];
    
    for (name, score) in items {
        println!("{} scored {}", name, score);
    }
    

    在这里,我们使用向量,因此在for循环后不再可以使用它。 namescore的所有权将转移到循环绑定中的变量。

    克隆项目

    let items = vec![("Peter".to_string(), 180)];
    
    let (name, score) = items[0].clone(); // Potential panic!
    println!("{} scored {}", name, score);
    

    在这里,我们在向量中创建项目的 new 版本。我们拥有新项目,矢量拥有原始项目。