SoFunction
Updated on 2025-04-09

How to store a list of values ​​using Rust's vector

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&lt;i32&gt; = 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 calledpushMethod 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 usinggetmethod.

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: &amp;i32 = &amp;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

getThe method will return aOption<&T>, return when access is out of rangeNoneInstead 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) =&gt; println!("The element is: {}", value),
        None =&gt; 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 = &amp;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 usedforcycle. 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 &amp;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) =&gt; println!("Integer: {}", value),
            SpreadsheetCell::Float(value) =&gt; println!("Float: {}", value),
            SpreadsheetCell::Text(text) =&gt; 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 passmatchStatements 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:useVec::newCreate an empty vector or usevec!Macros initialize vectors and master the difference between type inference and explicit annotations.
  • Update vector:passpushMethods add elements to vectors to understand the importance of variability.
  • Read vector elements: Comparison index syntax andgetAdvantages and disadvantages of the method, especially the difference when dealing with out-of-bounds access.
  • Traversal vectors: Demonstrate how to use itforThe 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 usematchStatements 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 asStringHashMap) 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.