[Avg. reading time: 16 minutes]

Vector Datatype

A Vector (Vec) is a growable, heap-allocated collection in Rust.

  • Size can grow or shrink at runtime
  • Stores elements of the same type
  • Allocated on the heap
  • Very commonly used in real-world Rust programs

Dynamic Arrays

Unlike fixed-size arrays [T; N], a Vec does not require size at compile time.

// Vector

fn main(){
    let mut my_vec = Vec::new();
    my_vec.push("Rachel");
    my_vec.push("Monica");
    my_vec.push("Phoebe");
    
    println!("{:?}",my_vec);
}

Capacity() vs Len()

capacity() number of elements the vector can hold (without reallocating memory). This is usually larger than or equal to the number of elements currently in the vector.

len() number of elements.

Inspecting Memory

use std::mem;

fn main(){
    let mut my_vec = Vec::new();
    my_vec.push("Rachel");
    my_vec.push("Monica");
    my_vec.push("Phoebe");
    
    println!("Vector Value {:?}", my_vec);
    println!("Address of Vec struct: {:p}", &my_vec);
    println!("Heap data pointer: {:p}", my_vec.as_ptr());
    println!("Length: {}", my_vec.len());
    println!("Capacity: {}", my_vec.capacity());
    println!("Heap bytes allocated: {}", my_vec.capacity() * mem::size_of::<String>());

    my_vec.push("Ross");
    my_vec.push("Chandler");
    my_vec.push("Joey");

    println!("Vector Value {:?}", my_vec);
    println!("Address of Vec struct: {:p}", &my_vec);
    println!("Heap data pointer: {:p}", my_vec.as_ptr());
    println!("Length: {}", my_vec.len());
    println!("Capacity: {}", my_vec.capacity());
    println!("Heap bytes allocated: {}", my_vec.capacity() * mem::size_of::<String>());
}

Len vs Allocated Capacity

["Rachel", "Monica", "Phoebe", _empty_]

["Rachel", "Monica", "Phoebe", "Ross", "Chandler", "Joey", _empty, _empty_]

Capacity common growth pattern

0 → 4 → 8 → 16 → 32 → ...

Room 126 - Classroom Capacity vs Number of students*

The vector structure itself lives on the stack, but its elements live on the heap.

A Vec internally stores:

+-------------------------+
| v (Vec<String>)         |
|-------------------------|
| ptr  ----+--------------|----+
| len  = 3 |              |    |
| cap  = 4 |              |    |
+-------------------------+    |
                               |
                               v
                              HEAP  

with_capacity()

The with_capacity() method in Rust is used to create a new, empty growable collection (like Vec or String) that pre-allocates a specific amount of memory on the heap.

This allows the collection to hold at least the specified number of elements without needing to reallocate memory as you add items, which can improve performance.

fn main() {
    let mut friends_default: Vec<String> = Vec::new();
    let mut friends_withcapacity: Vec<String> = Vec::with_capacity(5);

    println!("friends_default Initial len: {}", friends_default.len());
    println!("friends_default Initial cap: {}", friends_default.capacity());

    println!("friends_withcapacity Initial len: {}", friends_withcapacity.len());
    println!("friends_withcapacity Initial cap: {}", friends_withcapacity.capacity());

    friends_default.push("Rachel".to_string());
    friends_default.push("Monica".to_string());
    friends_default.push("Phoebe".to_string());

    friends_withcapacity.push("Rachel".to_string());
    friends_withcapacity.push("Monica".to_string());
    friends_withcapacity.push("Phoebe".to_string());

    println!("friends_default Final len: {}", friends_default.len());
    println!("friends_default Final cap: {}", friends_default.capacity());

    println!("friends_withcapacity Final len: {}", friends_withcapacity.len());
    println!("friends_withcapacity Final cap: {}", friends_withcapacity.capacity());
}

reserve()

Increases capacity after creation.

fn main(){
    let mut friends = Vec::new();
    friends.push("Rachel".to_string());
    friends.push("Monica".to_string());

    println!("friends before len: {}", friends.len());
    println!("friends before cap: {}", friends.capacity());

    friends.reserve(10);

    println!("friends after len: {}", friends.len());
    println!("friends after cap: {}", friends.capacity());

}

Vector with Datatypes

String Literal

fn main(){
    let mut my_vec: Vec<&str> = Vec::new();
    my_vec.push("Rachel");
    my_vec.push("Monica");
    my_vec.push("Phoebe");
    
    println!("{:?}",my_vec);
    
}

String Object


fn main(){
    let mut my_vec: Vec<String> = Vec::new();
    my_vec.push("Rachel".to_string());
    my_vec.push("Monica".to_string());
    my_vec.push("Phoebe".to_string());
   
    println!("{:?}",my_vec);  
}

Storing String literal on i32 (Error)

fn main(){
    let mut my_vec: Vec<i32> = Vec::new();
    
    my_vec.push("Rachel");
    my_vec.push("Monica");
    my_vec.push("Phoebe");
    
    println!("{:?}",my_vec);
    
}

Storing String Literal on String Object (Error)

fn main(){
    let mut my_vec: Vec<String> = Vec::new();
    my_vec.push("Rachel");
    my_vec.push("Monica");
    my_vec.push("Phoebe");
   
    println!("{:?}",my_vec);  
}

Vec Macro

  • Allocates a Vec
  • Infers the type
  • Inserts elements
  • Sets capacity efficiently

Without vec!

let mut friends = Vec::new();
friends.push("Rachel");
friends.push("Monica");
friends.push("Phoebe");

Using vec!

fn main(){
    let friends = vec!["Rachel", "Monica", "Phoebe"];
    println!("{:?}", friends);
}

Variables created using vector macro are also dynamic, stored in heap and reserved with more capacity.

fn main() {
    // Create a vector using the vec! macro
    let numbers = vec![2, 4, 6, 8, 10, 12, 14, 16];

    // Borrow different slices from the vector
    let slice_one   = &numbers[2..6];  // Index 2 up to (but not including) 6
    let slice_two   = &numbers[2..];   // Index 2 to end
    let slice_three = &numbers[..6];   // Start to index 6 (exclusive)
    let slice_four  = &numbers[..];    // Entire vector as a slice

    println!("Original Vector : {:?}", numbers);
    println!("Slice [2..6]    : {:?}", slice_one);
    println!("Slice [2..]     : {:?}", slice_two);
    println!("Slice [..6]     : {:?}", slice_three);
    println!("Slice [..]      : {:?}", slice_four);
}
[2, 4, 6, 8, 10, 12, 14, 16]
 0  1  2  3   4   5   6   7

[start..end] : start is inclusive - end is exclusive

Convert Array to Vector

This example demonstrates

  • Fixed-size array [T; N]
  • Converting array into Vec
  • Type inference using Vec<_>
  • Inspecting types at runtime
use std::any::type_name;

fn main() {
    // Fixed-size array (stack allocated)
    let arr = [1_i8, 2, 3, 4];

    // Explicit type conversion
    let vec_explicit: Vec<i8> = arr.into();

    // Type inference
    let vec_inferred: Vec<_> = arr.into();

    println!("Array       : {:?}", arr);
    println!("Vec explicit: {:?}", vec_explicit);
    println!("Vec inferred: {:?}", vec_inferred);

    println!("\nType Information:");
    print_type(&arr);
    print_type(&vec_explicit);
    print_type(&vec_inferred);
}

fn print_type<T>(_: &T) {
    println!("{}", type_name::<T>());
}

Sort the Vector

fn main() {
    let mut vec = vec![14, 33, 12, 3223, 2211, 9122, 3, 67];
    vec.sort();
    println!("Sorted: {:?}", vec)
}

#vector #dynamic #heap #arrayVer 2.0.12

Last change: 2026-02-18