]>
Commit | Line | Data |
---|---|---|
9346a6ac AL |
1 | % Vectors |
2 | ||
bd371182 AL |
3 | A ‘vector’ is a dynamic or ‘growable’ array, implemented as the standard |
4 | library type [`Vec<T>`][vec]. The `T` means that we can have vectors | |
5 | of any type (see the chapter on [generics][generic] for more). | |
6 | Vectors always allocate their data on the heap. | |
7 | You can create them with the `vec!` macro: | |
8 | ||
9 | ```rust | |
10 | let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32> | |
9346a6ac AL |
11 | ``` |
12 | ||
bd371182 | 13 | (Notice that unlike the `println!` macro we’ve used in the past, we use square |
7453a54e SL |
14 | brackets `[]` with `vec!` macro. Rust allows you to use either in either |
15 | situation, this is just convention.) | |
9346a6ac | 16 | |
bd371182 | 17 | There’s an alternate form of `vec!` for repeating an initial value: |
9346a6ac | 18 | |
62682a34 | 19 | ```rust |
9346a6ac AL |
20 | let v = vec![0; 10]; // ten zeroes |
21 | ``` | |
22 | ||
7453a54e SL |
23 | Vectors store their contents as contiguous arrays of `T` on the heap. This means |
24 | that they must be able to know the size of `T` at compile time (that is, how | |
25 | many bytes are needed to store a `T`?). The size of some things can't be known | |
26 | at compile time. For these you'll have to store a pointer to that thing: | |
27 | thankfully, the [`Box`][box] type works perfectly for this. | |
28 | ||
bd371182 AL |
29 | ## Accessing elements |
30 | ||
31 | To get the value at a particular index in the vector, we use `[]`s: | |
32 | ||
33 | ```rust | |
34 | let v = vec![1, 2, 3, 4, 5]; | |
35 | ||
36 | println!("The third element of v is {}", v[2]); | |
37 | ``` | |
38 | ||
39 | The indices count from `0`, so the third element is `v[2]`. | |
40 | ||
b039eaaf SL |
41 | It’s also important to note that you must index with the `usize` type: |
42 | ||
43 | ```ignore | |
44 | let v = vec![1, 2, 3, 4, 5]; | |
45 | ||
46 | let i: usize = 0; | |
47 | let j: i32 = 0; | |
48 | ||
49 | // works | |
50 | v[i]; | |
51 | ||
52 | // doesn’t | |
53 | v[j]; | |
54 | ``` | |
55 | ||
56 | Indexing with a non-`usize` type gives an error that looks like this: | |
57 | ||
58 | ```text | |
54a0048b SL |
59 | error: the trait bound `collections::vec::Vec<_> : core::ops::Index<i32>` |
60 | is not satisfied [E0277] | |
b039eaaf SL |
61 | v[j]; |
62 | ^~~~ | |
63 | note: the type `collections::vec::Vec<_>` cannot be indexed by `i32` | |
64 | error: aborting due to previous error | |
65 | ``` | |
66 | ||
67 | There’s a lot of punctuation in that message, but the core of it makes sense: | |
68 | you cannot index with an `i32`. | |
69 | ||
9cc50fc6 SL |
70 | ## Out-of-bounds Access |
71 | ||
72 | If you try to access an index that doesn’t exist: | |
73 | ||
74 | ```ignore | |
75 | let v = vec![1, 2, 3]; | |
76 | println!("Item 7 is {}", v[7]); | |
77 | ``` | |
78 | ||
79 | then the current thread will [panic] with a message like this: | |
80 | ||
81 | ```text | |
82 | thread '<main>' panicked at 'index out of bounds: the len is 3 but the index is 7' | |
83 | ``` | |
84 | ||
85 | If you want to handle out-of-bounds errors without panicking, you can use | |
86 | methods like [`get`][get] or [`get_mut`][get_mut] that return `None` when | |
87 | given an invalid index: | |
88 | ||
89 | ```rust | |
90 | let v = vec![1, 2, 3]; | |
91 | match v.get(7) { | |
92 | Some(x) => println!("Item 7 is {}", x), | |
93 | None => println!("Sorry, this vector is too short.") | |
94 | } | |
95 | ``` | |
96 | ||
bd371182 AL |
97 | ## Iterating |
98 | ||
99 | Once you have a vector, you can iterate through its elements with `for`. There | |
100 | are three versions: | |
9346a6ac | 101 | |
bd371182 AL |
102 | ```rust |
103 | let mut v = vec![1, 2, 3, 4, 5]; | |
9346a6ac | 104 | |
bd371182 AL |
105 | for i in &v { |
106 | println!("A reference to {}", i); | |
107 | } | |
9346a6ac | 108 | |
bd371182 AL |
109 | for i in &mut v { |
110 | println!("A mutable reference to {}", i); | |
111 | } | |
112 | ||
113 | for i in v { | |
114 | println!("Take ownership of the vector and its element {}", i); | |
115 | } | |
9346a6ac AL |
116 | ``` |
117 | ||
54a0048b SL |
118 | Note: You cannot use the vector again once you have iterated by taking ownership of the vector. |
119 | You can iterate the vector multiple times by taking a reference to the vector whilst iterating. | |
120 | For example, the following code does not compile. | |
121 | ||
122 | ```rust,ignore | |
123 | let v = vec![1, 2, 3, 4, 5]; | |
124 | ||
125 | for i in v { | |
126 | println!("Take ownership of the vector and its element {}", i); | |
127 | } | |
128 | ||
129 | for i in v { | |
130 | println!("Take ownership of the vector and its element {}", i); | |
131 | } | |
132 | ``` | |
133 | ||
134 | Whereas the following works perfectly, | |
135 | ||
136 | ```rust | |
137 | let v = vec![1, 2, 3, 4, 5]; | |
138 | ||
139 | for i in &v { | |
140 | println!("This is a reference to {}", i); | |
141 | } | |
142 | ||
143 | for i in &v { | |
144 | println!("This is a reference to {}", i); | |
145 | } | |
146 | ``` | |
147 | ||
bd371182 AL |
148 | Vectors have many more useful methods, which you can read about in [their |
149 | API documentation][vec]. | |
150 | ||
151 | [vec]: ../std/vec/index.html | |
7453a54e | 152 | [box]: ../std/boxed/index.html |
bd371182 | 153 | [generic]: generics.html |
9cc50fc6 SL |
154 | [panic]: concurrency.html#panics |
155 | [get]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get | |
156 | [get_mut]: http://doc.rust-lang.org/std/vec/struct.Vec.html#method.get_mut |