1. Create a new vector
Rust provides two common ways to create vectors:
Using Vec::new
When you need to create an empty vector, you can call itVec::new
。
Note that since there are no elements in the vector, the compiler cannot automatically infer the types of elements in the vector, so type annotations are usually needed.
For example:
fn main() { // Create an empty Vec<i32> let mut v: Vec<i32> = Vec::new(); // Add elements to the vector (5); (6); (7); (8); println!("Vector: {:?}", v); }
Use the vec! macro
If you want to initialize the vector and specify the initial value from the beginning, you can usevec!
Macro.
Rust will automatically deduce the type of vector element based on the given initial value:
fn main() { // Create a vector with the initial values 1, 2, 3, the type will be inferred as Vec<i32> let v = vec![1, 2, 3]; println!("Vector: {:?}", v); }
2. Update vector
Vectors are dynamically sized data structures, which can be calledpush
Method adds new elements to the vector.
It should be noted that if you want to modify the content of a vector, the variable must be declared as mutable (mut
):
fn main() { let mut v = vec![1, 2, 3]; // Add elements to the end of the vector (4); (5); println!("Updated vector: {:?}", v); }
3. Read elements in vector
There are two main ways to read vector elements: using index syntax and usingget
method.
3.1 Using index syntax
Use index syntax to directly obtain elements in a vector at a specified position.
For example:
fn main() { let v = vec![10, 20, 30, 40, 50]; let third: &i32 = &v[2]; // Note: The index starts at 0, so index 2 represents the third element println!("The third element is: {}", third); }
Notice: If the index goes beyond the range of the vector (for example, accessing an element that does not exist), using the index syntax will cause the program to panic, thus crashing.
3.2 Using the get method
get
The method will return aOption<&T>
, return when access is out of rangeNone
Instead of panic, it can be matched by (match
) or other ways to handle this situation safely:
fn main() { let v = vec![10, 20, 30, 40, 50]; // Try to get an element with index of 100 match (100) { Some(value) => println!("The element is: {}", value), None => println!("There is no element at index 100."), } }
4. Vector and Borrow Checker
Rust's borrowing rules ensure the security of references to vector elements.
For example, if we try to modify the vector when holding an immutable reference to an element, it will trigger the borrow checker to report an error:
fn main() { let mut v = vec![1, 2, 3]; // Get the immutable reference to the first element let first = &v[0]; // Try to add a new element to the vector // (4); // This line of code will cause compilation errors, because immutable references and mutable operations cannot coexist. println!("The first element is: {}", first); }
The reason is that vectors are stored continuously in memory, and adding new elements may cause memory redistribution, thereby invalidating existing references. Borrowing inspectors can capture this potential security issue during compilation.
5. Traversing the vector
Traversal vectors are usually usedfor
cycle. You can choose immutable traversal or variable traversal to modify elements.
5.1 Immutable traversal
The following code demonstrates how to traverse each element in a vector with immutable references and print it out:
fn main() { let v = vec![100, 32, 57]; for i in &v { println!("The value is: {}", i); } }
5.2 Variable traversal
If you need to modify each element in the vector, you can traverse it through mutable references:
fn main() { let mut v = vec![100, 32, 57]; for i in &mut v { // Use the dereference operator * to modify the value pointed to by the reference *i += 50; } println!("Modified vector: {:?}", v); }
6. Use enumeration to store different types of values
Vectors require that all elements must be of the same type, but in some cases you may need to store different types of values in the same vector. To solve this problem, you can define an enum, take all possible types as different variants of the enum, and then store the enum instance in the vector:
// Define an enum to represent different types that may appearenum SpreadsheetCell { Int(i32), Float(f64), Text(String), } fn main() { // Create a vector that stores SpreadsheetCell enumerations let row = vec![ SpreadsheetCell::Int(3), SpreadsheetCell::Float(10.12), SpreadsheetCell::Text(String::from("blue")), ]; // traverse the vector and match according to the variant of each enum for cell in row { match cell { SpreadsheetCell::Int(value) => println!("Integer: {}", value), SpreadsheetCell::Float(value) => println!("Float: {}", value), SpreadsheetCell::Text(text) => println!("Text: {}", text), } } }
This way ensures that all values in vectors belong to the same type (i.e., enum type), while allowing us to store values of different "actual" types and passmatch
Statements check every possible situation at compile time.
7. Memory release of vectors
The vector in Rust will be automatically released after it is out of scope, and all elements in the vector will be dropped (destroyed). This mechanism ensures automatic memory recovery.
For example:
fn main() { { let v = vec![1, 2, 3, 4]; // Here v and the values in it are valid println!("Vector inside scope: {:?}", v); } // After leaving the scope, v is automatically dropped and the memory is freed // Here v is no longer valid}
The borrow checker also ensures that after the vector is dropped, there is no longer a valid reference to the elements in it.
Summarize
This article describes how to use vectors to store a list of values in Rust, including the following aspects:
-
Create a vector:use
Vec::new
Create an empty vector or usevec!
Macros initialize vectors and master the difference between type inference and explicit annotations. -
Update vector:pass
push
Methods add elements to vectors to understand the importance of variability. -
Read vector elements: Comparison index syntax and
get
Advantages and disadvantages of the method, especially the difference when dealing with out-of-bounds access. -
Traversal vectors: Demonstrate how to use it
for
The loop performs immutable and mutable traversal of the vector and illustrates how elements are modified using dereference operators. -
Store multiple types: Define enumeration to store different types of values in a vector, and use
match
Statements are checked at compile time. - Free vector: It means that the vector will be automatically released after it exceeds scope, and the elements in the vector will also be dropped to ensure memory security.
Vectors are commonly used and powerful collection types in Rust. Proficient in their usage can help you write efficient and safe code. Next, you can continue to explore other collection types in Rust (such asString
、HashMap
) The use method further improves the organization and data processing capabilities of the project.
The above is personal experience. I hope you can give you a reference and I hope you can support me more.