Oliot, osoittimet ja taulukot

Taulukot


Olemme käyttäneet STL:n vector-rakennetta, kun saman tyyppisiä arvoja tallennetaan järjestyksessä ja niihin halutaan viitata indeksillä. C++:ssa on myös alkeellisempi samankaltainen tietorakenne, taulukko (array).

Taulukko on yksinkertainen, kiinteän kokoinen eli staattinen tietorakenne. Sen yksittäisiin alkioihin viitataan []-operaattorilla. Taulukot ovat peräisin C-kielestä, johon C++ pohjautuu. Tällä kurssilla niiden sijaan kannattaa yleensä käyttää vektoria, mutta taulukoiden tuntemisesta on hyötyä esimerkiksi C-koodia lukiessa.

Taulukon määrittely ja käyttö

Seuraava määrittely varaa tilan kolmelle int-alkiolle:

int luvut[3];

Alkiot tallennetaan yhtenäiseen muistialueeseen:

Kolmelle kokonaisluvulle varatut peräkkäiset muistipaikat taulukossa
Taulukon alkiot sijaitsevat muistissa peräkkäin.

Indeksointi alkaa nollasta, joten tämän taulukon indeksit ovat 0, 1 ja 2. Ennen alkion lukemista sille täytyy olla annettu arvo:

luvut[0] = 6;
luvut[1] = 12;
luvut[2] = 24;

cout << luvut[0] + luvut[2] << endl;  // 30

Tallennettujen arvojen jälkeen muistia voi hahmottaa näin:

Taulukon kolme muistipaikkaa sisältävät arvot 6, 12 ja 24
Taulukon muistipaikkoihin sijoitetut arvot.

Taulukon koko ei muutu suorituksen aikana. Esimerkiksi kolmen alkion taulukkoon ei voi lisätä neljättä alkiota. Lisäksi indeksin täytyy aina olla sallitulla välillä; rajan ulkopuolelta lukeminen tai kirjoittaminen aiheuttaa määrittelemätöntä toimintaa.

Taulukon nimi ja osoittimet

Taulukko ei ole sama asia kuin osoitin. Useimmissa lausekkeissa taulukon nimi kuitenkin muuntuu osoittimeksi sen ensimmäiseen alkioon. Tämän vuoksi taulukon voi sijoittaa osoitinmuuttujaan ja sitä voi käsitellä osoitinaritmetiikalla.

int* taulukko_osoitin = luvut;

Kun taulukon nimi tulostetaan osoitinta odottavassa yhteydessä, tuloksena on ensimmäisen alkion osoite. Osoitteen tarkka esitysmuoto riippuu järjestelmästä.

Taulukon nimi ei kuitenkaan ole uudelleen sijoitettava osoitinmuuttuja. Tästä seuraa muutamia eroja vektoriin ja tavalliseen osoittimeen:

  • Taulukkoa ei voi sijoittaa toiseen taulukkoon =-operaattorilla eikä alustaa toisesta taulukosta.
  • Kun taulukko annetaan funktion parametrina, parametrin tyyppi mukautuu käytännössä osoittimeksi ensimmäiseen alkioon. Funktiolle täytyy yleensä välittää myös alkioiden määrä, koska pelkkä osoitin ei kerro taulukon kokoa.
  • Raakaa C++-taulukkoa ei voi käyttää suoraan STL-säiliön alkion tyyppinä. STL:n array-säiliö on eri rakenne.

Taulukon läpikäynti osoittimella

Taulukon voi käydä läpi osoittimen avulla. Osoitinta kasvatetaan yksi alkio kerrallaan, ja silmukka pysähtyy kohtaan, joka on heti viimeisen alkion jälkeen:

int* taulukko_osoitin = luvut;
while (taulukko_osoitin < luvut + 3) {
    cout << *taulukko_osoitin << endl;
    ++taulukko_osoitin;
}

Osoittimeen voi lisätä kokonaisluvun: luvut + 1 osoittaa toiseen alkioon ja luvut + 3 kohtaan taulukon lopun jälkeen. Tätä kutsutaan osoitinaritmetiikaksi. Osoittimen kasvatus siirtyy seuraavaan alkioon, ei välttämättä vain yhden tavun verran.

Yhden alkion jälkeiseen kohtaan osoittaminen on sallittua ja sitä käytetään usein silmukan lopetusrajana. Tätä osoitinta ei kuitenkaan saa dereferoida, sillä se ei osoita taulukon alkioon.

Taulukkoindeksointi perustuu samaan osoitinaritmetiikkaan. Esimerkiksi nämä koodit ovat merkitykseltään yhtäpitävät:

cout << luvut[2] << endl;
luvut[1] = 99;
cout << *(luvut + 2) << endl;
*(luvut + 1) = 99;

Yhteenveto

Taulukot ovat kiinteän kokoisia, peräkkäiseen muistiin tallennettavia alkioita. Niiden nimi muuntuu monissa lausekkeissa osoittimeksi ensimmäiseen alkioon, mikä mahdollistaa osoitinaritmetiikan mutta tuo mukanaan myös rajoja ja virhemahdollisuuksia. Kurssin tehtävissä vektori on yleensä helpompi ja turvallisempi vaihtoehto; taulukon toimintaperiaatteen ymmärtäminen auttaa silti matalamman tason C- ja C++-koodin lukemisessa.

Video: Taulukoiden vaaroja (8 min)

Taulukot ovat edelleen tarpeellisia matalan tason ohjelmoinnissa, mutta erityisesti indeksien kanssa pitää olla tarkkana: virheellinen indeksi voi aiheuttaa vaikeasti löydettäviä ongelmia.

Avaa Taulukoiden vaaroja -video (8 min)