Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Globaalit vs. paikalliset muuttujat ja taulukot

jone2712 [25.10.2017 11:40:51]

#

Melkein aina, kun raapii tarpeeksi kauan päätä, niin globaalit muuttujat ja taulukou voi korvata pinosta lohkaistulla segmentillä. Mutta on tilanteita, jolloin globaalin muuttujan ja taulukon olisi koodin kannalta helpompaa määritellä funktioiden ulkopuolella.

Onko pinossa esitelty muuttuja nopeampaa käyttää kuin globaalia muuttujaa.

Esim:

int taulukko[1<<16];

void funktio(void)
{
   koodia...
}

void main(void)
{
   funktio();
}

Vai seuraavanlaisesti:

void funktio(int *taulukko)
{
   koodia...
}

void main(void)
{
   int *taulukko=new int[1<<16];
   funktio(taulukko);
}

jone2712 [25.10.2017 15:28:32]

#

Liekö taulukon määrittely:

int *taulukko=new int[1<<16];

varaavan muutenkin taulukon globaaliin muistiin?

Pitäisi olla järkevämmän oloinen pinomuistin varaus:

int taulukko[4096];

Metabolix [25.10.2017 19:01:38]

#

Aivan, new varaa muistin keosta (heap), mikä vie ylimääräistä aikaa, ja muistin käyttäminen osoittimen kautta voi myös olla periaatteessa hitaampaa kuin globaalin muuttujan käyttö. Pinomuistin käyttö voi olla nopeinta, mutta se riippuu tilanteesta.

Erot tulevat lähinnä siitä, montako muistihakua täytyy tehdä ja mitä dataa sattuu olemaan valmiiksi prosessorin välimuistissa. Pinon sisältö on lähes varmasti jo välimuistissa, joten pinotaulukon käyttö voi alkaa joitain mikrosekunteja nopeammin kuin globaalin taulukon, mutta käytön jatkuessa (esim. silmukassa) ero katoaa. Osoittimen tapauksessa joudutaan hakemaan ensin osoittimen arvo ja sitten vasta data, kun taas globaalin taulukon ja oikean pinotaulukon osoite on valmiiksi tiedossa. Toisaalta kääntäjä usein optimoi koodia niin, että osoite haetaan vain kerran, jolloin asialla ei ole käytännön merkitystä. Tärkeintä olisi välttää ylimääräisiä new-kutsuja varsinkin funktioissa, joita käytetään toistuvasti.

Sitä paitsi new on vaarallinen, koska muisti jää helposti vapauttamatta. Kannattaa käyttää turvallisia menetelmiä kuten std::vector-tyyppiä.

// nopein (?), mutta taulukon maksimikoko on varsin rajallinen
void f1() {
  int t1[1024];
}

// käytännössä yhtä nopea, ja mahtuu isompikin taulukko
int t2[1024];
void f2() {
}

// vähän hitaampi muistin varaamisen takia, mutta muisti myös vapautuu
void f3() {
  std::vector<int> t3(1024);
}

// yhtä hidas, ja lisäksi muisti jää vapauttamatta, VIRHE!
void f4() {
  int *t4 = new int[1024];
}

jone2712 [28.10.2017 11:02:20]

#

Ok. Kiitos informatiivisesta vastauksesta ja esimerkkifunktioista.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta