• Vectors
    • 访问元素
    • 越界访问(Out-of-bounds Access)
    • 迭代

    Vectors

    vectors.md


    commit 23a7a7bdb6a6a43cd7efdd9176b1d3f75d9d0e70

    “Vector”是一个动态或“可增长”的数组,被实现为标准库类型Vec<T>(其中<T>是一个泛型语句)。vector 总是在堆上分配数据。vector 与切片就像String&str一样。你可以使用vec!宏来创建它:

    1. let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>

    (与之前使用println!宏时不一样,我们用中括号[]配合vec!。为了方便,Rust 允许使用上述各种情况。)

    对于重复初始值有另一种形式的vec!

    1. let v = vec![0; 10]; // ten zeroes

    vector 将它们的内容以连续的T的数组的形式存储在堆上,这意味着它们必须在编译时就知道T的大小(就是存储一个T需要多少字节)。有些类型的大小不可能在编译时就知道。为此你需要保存一个指向该类型的指针:幸好,Box类型正好适合这种情况。

    访问元素

    为了vector特定索引的值,使用[]

    1. let v = vec![1, 2, 3, 4, 5];
    2. println!("The third element of v is {}", v[2]);

    索引从0开始,所以第 3 个元素是v[2]

    另外值得注意的是必须用usize类型的值来索引:

    1. let v = vec![1, 2, 3, 4, 5];
    2. let i: usize = 0;
    3. let j: i32 = 0;
    4. // Works:
    5. v[i];
    6. // Doesn’t:
    7. v[j];

    用非usize类型索引的话会给出类似如下的错误:

    1. error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>`
    2. is not satisfied [E0277]
    3. v[j];
    4. ^~~~
    5. note: the type `collections::vec::Vec<_>` cannot be indexed by `i32`
    6. error: aborting due to previous error

    信息中有很多标点符号,不过关键是:你不能用i32来索引。

    越界访问(Out-of-bounds Access)

    如果尝试访问并不存在的索引:

    1. let v = vec![1, 2, 3];
    2. println!("Item 7 is {}", v[7]);

    那么当前的线程会 panic并输出如下信息:

    1. thread 'main' panicked at 'index out of bounds: the len is 3 but the index is 7'

    如果你想处理越界错误而不是 panic,你可以使用像getget_mut这样的方法,他们当给出一个无效的索引时返回None

    1. let v = vec![1, 2, 3];
    2. match v.get(7) {
    3. Some(x) => println!("Item 7 is {}", x),
    4. None => println!("Sorry, this vector is too short.")
    5. }

    迭代

    可以用for来迭代 vector 的元素。有3个版本:

    1. let mut v = vec![1, 2, 3, 4, 5];
    2. for i in &v {
    3. println!("A reference to {}", i);
    4. }
    5. for i in &mut v {
    6. println!("A mutable reference to {}", i);
    7. }
    8. for i in v {
    9. println!("Take ownership of the vector and its element {}", i);
    10. }

    注意:你不能在使用 vector 的所有权遍历之后再次遍历它。你可以使用它的引用多次遍历 vector。例如,下面的代码不能编译。

    1. let v = vec![1, 2, 3, 4, 5];
    2. for i in v {
    3. println!("Take ownership of the vector and its element {}", i);
    4. }
    5. for i in v {
    6. println!("Take ownership of the vector and its element {}", i);
    7. }

    而如下代码则可以完美运行:

    1. let v = vec![1, 2, 3, 4, 5];
    2. for i in &v {
    3. println!("This is a reference to {}", i);
    4. }
    5. for i in &v {
    6. println!("This is a reference to {}", i);
    7. }

    vector还有很多有用的方法,可以看看vector的API文档了解它们。