Vec::with_capacity în Rust

Creează un vector cu loc rezervat dinainte; capacity spune cât loc are, iar reserve mărește locul fără să adauge elemente.

Sintaxă
pub fn with_capacity(capacity: usize) -> Vec<T>
pub fn capacity(&self) -> usize
pub fn reserve(&mut self, additional: usize)

Ce face Vec::with_capacity

Un Vec are două mărimi: lungimea (len(), câte elemente are) și capacitatea (capacity(), câte elemente încap fără o nouă alocare de memorie). Când lungimea ajunge la capacitate și mai adaugi un element, vectorul alocă o zonă mai mare (de obicei dublă), copiază elementele acolo și eliberează zona veche.

Vec::with_capacity(n) creează un vector gol (lungime 0) care are deja loc pentru cel puțin n elemente. Dacă știi dinainte câte elemente vei adăuga, eviți realocările repetate. reserve(n) face același lucru pe un vector existent: garantează loc pentru încă n elemente peste lungimea actuală (poate rezerva și mai mult).

Capacitatea nu schimbă ce conține vectorul, doar cât de des se alocă memorie. Pentru a elibera locul nefolosit există shrink_to_fit(), iar reserve_exact(n) rezervă exact cât ceri.

Parametri

Parametru Descriere
capacity La with_capacity: câte elemente să încapă fără realocare.
additional La reserve: câte elemente în plus față de len() trebuie să încapă.

Ce returnează

with_capacity returnează un vector gol; capacity returnează un usize; reserve nu returnează nimic.

Exemple

Exemplul 1: Cum crește capacitatea la push

Afișăm doar momentele în care capacitatea se schimbă. Pentru elemente mici, biblioteca standard pornește de la 4 și dublează.

fn main() {
    let mut v: Vec<i32> = Vec::new();
    println!("la început: len = {}, capacity = {}", v.len(), v.capacity());
    for i in 1..=10 {
        let inainte = v.capacity();
        v.push(i);
        if v.capacity() != inainte {
            println!("după push({i}): capacity {inainte} -> {}", v.capacity());
        }
    }
    println!("la final: len = {}, capacity = {}", v.len(), v.capacity());
}

Rezultat

la început: len = 0, capacity = 0
după push(1): capacity 0 -> 4
după push(5): capacity 4 -> 8
după push(9): capacity 8 -> 16
la final: len = 10, capacity = 16

Exemplul 2: with_capacity când știi câte elemente vin

Cu loc pentru 1000 de elemente, cele 1000 de push nu realocă deloc. Abia elementul 1001 forțează o zonă nouă.

fn main() {
    let n = 1000;
    let mut v = Vec::with_capacity(n);
    let initiala = v.capacity();
    for i in 0..n {
        v.push(i * 2);
    }
    println!("len = {}, capacity = {} (inițial {})", v.len(), v.capacity(), initiala);

    v.push(0);
    println!("după încă un push: len = {}, capacity = {}", v.len(), v.capacity());
}

Rezultat

len = 1000, capacity = 1000 (inițial 1000)
după încă un push: len = 1001, capacity = 2000

Exemplul 3: reserve și shrink_to_fit

reserve(10) pe un vector cu 2 elemente garantează loc pentru cel puțin 12. shrink_to_fit eliberează surplusul.

fn main() {
    let mut nume = vec![String::from("Ana"), String::from("Mihai")];
    println!("la început: len = {}, capacity = {}", nume.len(), nume.capacity());

    nume.reserve(10);
    println!("după reserve(10): len = {}, capacity = {}", nume.len(), nume.capacity());

    nume.push(String::from("Ioana"));
    nume.shrink_to_fit();
    println!("după shrink_to_fit: len = {}, capacity = {}", nume.len(), nume.capacity());
}

Rezultat

la început: len = 2, capacity = 2
după reserve(10): len = 2, capacity = 12
după shrink_to_fit: len = 3, capacity = 3

Greșeli frecvente

  • Crezi că Vec::with_capacity(5) creează 5 elemente. Vectorul este gol: v[0] dă panic. Pentru 5 elemente egale folosește vec![0; 5] sau resize.
  • Te bazezi pe o valoare exactă a capacității după reserve sau după push. Documentația garantează doar „cel puțin”; strategia de creștere se poate schimba între versiuni.
  • Apelezi reserve(1) înainte de fiecare push. Nu câștigi nimic: push deja crește inteligent. Rezervă o singură dată, cu numărul total.

Comenzi înrudite

  • Vec: Vectorul dinamic din Rust: o listă de elemente de același tip, ținute unul după altul în memorie, care crește singură.
  • Vec::push: push adaugă un element la sfârșitul vectorului; pop îl scoate pe ultimul și îl returnează ca Option.
  • Vec::len: len returnează numărul de elemente din vector; is_empty spune dacă vectorul nu are niciun element.
  • Vec::truncate: truncate păstrează doar primele len elemente; clear golește vectorul. Ambele lasă capacitatea neschimbată.
  • Vec::resize: Schimbă lungimea vectorului: îl taie dacă e prea lung sau adaugă copii ale unei valori până la noua lungime.