Ce face const și static
const definește o constantă: o valoare cunoscută la compilare, cu tipul scris obligatoriu și numele cu majuscule (const TVA: f64 = 0.21;). Compilatorul copiază valoarea în fiecare loc unde este folosită, ca și cum ai fi scris-o acolo.
static definește un element global care există o singură dată în memorie, pe toată durata programului (are durata de viață 'static). Îl folosești când ai nevoie de o adresă fixă, de exemplu pentru un tabel mare sau pentru un contor atomic partajat de fire.
static mut există, dar orice acces la el cere unsafe, iar în ediția 2024 referințele la un static mut sunt eroare. Pentru stare globală modificabilă folosește tipuri sigure: AtomicU32, Mutex, OnceLock, LazyLock. const fn marchează funcțiile care pot fi apelate în inițializarea unei constante.
Exemple
Exemplul 1: Constante pentru valori fixe
LEI_PE_EURO și PRAG_TRANSPORT sunt calculate la compilare. Și LIMITA_BANI este o constantă, calculată de o const fn din altă constantă.
const LEI_PE_EURO: f64 = 4.97;
const PRAG_TRANSPORT: u32 = 150;
const LIMITA_BANI: u32 = in_bani(PRAG_TRANSPORT);
const fn in_bani(lei: u32) -> u32 {
lei * 100
}
fn main() {
let cos = 180;
println!("Coș: {cos} lei = {:.2} euro", cos as f64 / LEI_PE_EURO);
if cos >= PRAG_TRANSPORT {
println!("Transport gratuit (prag: {PRAG_TRANSPORT} lei = {LIMITA_BANI} bani)");
}
}
Rezultat
Coș: 180 lei = 36.22 euro
Transport gratuit (prag: 150 lei = 15000 bani)
Exemplul 2: static cu un contor atomic
VIZITE este o singură variabilă globală, modificată sigur din patru fire de execuție, fără unsafe, prin operații atomice. NUME_SITE este un text static.
use std::sync::atomic::{AtomicU32, Ordering};
use std::thread;
static NUME_SITE: &str = "dexblog.ro";
static VIZITE: AtomicU32 = AtomicU32::new(0);
fn main() {
let fire: Vec<_> = (0..4)
.map(|_| thread::spawn(|| {
for _ in 0..250 {
VIZITE.fetch_add(1, Ordering::Relaxed);
}
}))
.collect();
for f in fire {
f.join().unwrap();
}
println!("{NUME_SITE}: {} vizite", VIZITE.load(Ordering::Relaxed));
}
Rezultat
dexblog.ro: 1000 vizite
Greșeli frecvente
- Omiți tipul:
const TVA = 0.21;nu se compilează. Laconstșistatictipul este obligatoriu. - Inițializezi un
constcu ceva care nu se poate calcula la compilare, de exempluString::from("x")sau o funcție obișnuită. Folosește&str, oconst fnsauLazyLockpentru valori calculate la prima folosire. - Folosești
static mutpentru un contor global. Ai nevoie deunsafela fiecare acces și riști curse de date între fire; unAtomicU32sau unMutexface același lucru în siguranță.
Comenzi înrudite
variabile și mutabilitate (let, mut): let creează o variabilă. Implicit nu poate fi modificată; cu let mut primește voie să-și schimbe valoarea.lifetimes (durate de viață, 'a): Adnotări ca ‘a care spun compilatorului cât timp trebuie să rămână valide referințele, ca să nu existe niciodată o referință spre memorie eliberată.unsafe și pointeri bruți: unsafe permite cinci operații pe care compilatorul nu le poate verifica, ca dereferențierea pointerilor bruți; corectitudinea o garantezi tu.thread_local!: Declară variabile statice de care fiecare fir de execuție are propria copie, inițializată la prima folosire în acel fir.