ALGO25 / BLOG

Inițializarea tablourilor locale și globale în C++

Nu presupune că un tablou local începe cu zero. Separă capacitatea de valorile inițiale și alege explicit starea necesară algoritmului tău.

Declarația unui tablou rezervă elemente, dar nu înseamnă întotdeauna că fiecare element primește valoarea zero. Comportamentul depinde de forma inițializării și de durata de stocare a obiectului. O soluție corectă nu trebuie să depindă de valori întâmplătoare din memorie.

Tabloul local fără inițializator

Pentru un tablou local obișnuit de int, declarat fără inițializator, nu ai dreptul să presupui că elementele sunt zero. Citirea unor valori întregi neinițializate nu este o metodă validă de a obține „numere aleatoare” și poate duce la comportament nedefinit în C++17.

Dacă citești ulterior fiecare element folosit înainte de orice altă citire a lui, programul poate fi corect. Problema apare când incrementezi, compari sau aduni o poziție înainte să îi atribui o valoare definită.

Inițializarea explicită exprimă intenția

O declarație cu inițializator gol, precum int frecventa[10] = {};, inițializează elementele la zero. Pentru un vector de int construit cu zece elemente și alocatorul obișnuit, elementele sunt de asemenea inițializate cu zero.

Aceste forme sunt potrivite pentru un tablou de frecvențe: fiecare contor trebuie să înceapă de la zero înainte de incrementare. Pentru distanțe sau stări imposibile, zero poate avea alt sens, deci inițializarea trebuie adaptată modelului.

Un tablou local automat fără inițializator nu oferă valori zero garantate. Inițializatorul gol pune int-urile la zero; stocarea statică are și ea inițializare zero.Un tablou local automat fără inițializator nu oferă valori zero garantate. Inițializatorul gol pune int-urile la zero; stocarea statică are și ea inițializare zero.Mărește schema ↗

Stocarea statică are alte reguli

Tablourile globale și cele cu durată de stocare statică sunt inițializate cu zero înaintea celorlalte inițializări aplicabile. Această regulă nu trebuie transferată automat unui tablou local automat mutat într-o funcție.

În plus, un tablou static își păstrează valorile între apeluri. Dacă îl folosești pentru mai multe cazuri de test, ai nevoie să resetezi explicit starea necesară fiecărui caz. Inițializarea de la pornirea programului nu se repetă la fiecare apel.

Testează două cazuri consecutive

Un test izolat poate ascunde faptul că frecvențele sau marcajele rămân din cazul anterior. Rulează două cazuri diferite în același proces și compară al doilea rezultat cu o rulare separată a lui.

Verifică fiecare citire: de unde provine valoarea și când a fost atribuită? Această întrebare este mai precisă decât speranța că mediul de execuție a umplut memoria cu zero. Capacitatea rezervată și starea inițială sunt două decizii distincte.

Revezi tablourile, vectorii de frecvență și subprogramele.

Întrebări frecvente

Un tablou local de int este inițializat automat cu zero?

Nu dacă este un tablou automat obișnuit declarat fără inițializator. Nu citi elementele înainte să le atribui valori. În C++17, asemenea citiri pot avea comportament nedefinit.

Cum inițializez toate elementele unui tablou cu zero?

O inițializare precum int a[100]{}; pune elementele la zero. Dacă tabloul există deja, atribuie explicit valorile necesare, de exemplu prin std::fill pe intervalul dorit.

De ce un tablou global poate părea diferit de unul local?

Obiectele cu durată de stocare statică sunt inițializate cu zero înaintea celorlalte etape aplicabile. Mutarea tabloului într-o funcție poate schimba această proprietate dacă devine un obiect automat fără inițializator.