Premenné

Globálne premenné:

  • vzniknú pri spustení programu
  • existujú počas behu programu
  • zanikajú pri skočení programu
  • počas kompilácie sa rozhodne, kde v pamäti budú takéto premenné umiestnené.

Lokálne premenné (a parametre):

  • vznikajú pri zavolaní funkcie
  • existujú počas vykonávania funkcie
  • zaniknú pri skončení funkcie
  • vznikajú v časti pamäte, ktorej hovoríme zásobník.

Veľkosť (počet bajtov) globálnej a lokálnej premennej je určená už počas kompilácie programu.

Niekedy je výhodné, ak môžeme riadiť vznikanie a zanikanie premenných a to hlavne takých, ktoré:

  • nemajú v čase kompilácie programu presne stanovenú veľkosť
  • počas behu programu menia svoju veľkosť (zoznamy)
  • v pamäti zaberajú veľa miesta (veľké objekty, štruktúry, obrázky), a pritom potrebujeme iba na určitú dobu.

Dynamické premenné:

  • ich vznik a zánik riadime pomocou príkazov
  • vytvoríme ju v okamihu, keď premennú potrebujeme
  • zrušíme ju, keď už premennú nepotrebujeme
  • vznikajú v časti pamäte, ktorú nazývame halda (anglicky heap).

Dynamické premenné

Pri kompilácii sa nedá presne určiť, kde v pamäti dynamická premenná vznikne - aká bude jej adresa. Preto pri práci s dynamickými premennými používame smerníky, ktoré na dynamické premenné ukazujú:

float *p; // smerník na premennú typu float p=new float; // vytvoríme premennú typu float a jej adresu uložíme do smerníka p *p=3.14; // teraz môžeme pracovať s dynamickou premennou *p (priradíme hodnotu) Caption=FloatToStr(*p); delete p; // zrušíme dynamickú premennú

  • Operátor new nájde v halde voľné miesto, na ktorom vytvorí dynamickú premennú uvedeného typu. Výsledkom operátora je smerník na novovzniknutú dynamickú premennú.
  • S dynamickou premennou ďalej pracujeme pomocou smerníka.
  • Operátor delete zruší dynamickú premennú - uvoľní v halde pamäťové miesto. Od tohto okamihu smerník ukazuje na neexistujúcu premennú (pozor, v smerníku nebude hodnota NULL).

Pozn.: z dôvodu kompatibility typov nasledujúce neskompilujeme: p=new int; … chyba Smerník na premennú typu float nie je kompatibilný so smerníkom na premennú typu int - výsledkom operácie new int je smerník na celočíselná premenná.

Pravidlá a odporúčania pri práci s dynamickou premennou

  • 1. Po zrušení dynamickej premennej už s touto premennou nesmieme pracovať - čiže, nesmieme:

p=new float; delete p; Caption=FloatToStr(*p); ... premenná, ktorá bola na adrese p už neexistuje

Kompilátor príkazy preloží, ale chyba sa vyskytne až pri vykonávaní posledného príkazu, ktorý zisťuje obsah už neexistujúcej premennej (uvoľnené pamäťové miesto sa použije na niečo iné).

  • 2. Nesmieme vykonať viacnásobné zrušenie jednej dynamickej premennej:

p=new float; delete p; // zrušíme premennú *p delete p; ... nesmieme zrušiť neexistujúcu premennú

Podobne, ako v predchádzajúcom príklade, aj tieto príkazy sa skompilujú, avšak chyba sa môže prejaviť až pri behu programu.

Treba si zapamätať pravidlo:

Každú premennú vytvorenú príkazom new musíme zrušiť príkazom delete.

  • 3. Ak je šanca, že v programe budeme rušiť tú istú dynamickú premennú na viacerých miestach, potom používame nasledovnú možnosť:
p=new float; ... delete p; // zrušíme premennú *p p=NULL; // smerník neukazuje na žiadnu premennú ... delete p; // ak p ukazuje na dynamickú premennú, týmto príkazom ju zrušíme, ak je p==NULL, nič sa nestane p=NULL;

4. V programoch môžeme použiť smerník aj viackrát:

p=new float; delete p; p=new float; delete p;

5. Dávajte si pozor na nasledujúce:

p=new float; p=new float; // ... stratili sme adresu predchádzajúcej dynamickej premennej delete p; ... teraz už nesmieme vykonať: delete p ... predchádzajúcim príkazom sme dynamickú premennú, na ktorú smerník p ukazoval, už zrušili.

Príklady s dynamickými premennými

Objekt ako dynamická premenná:

TKor *k; k=new TKor; // vytvoríme objekt k->dp(100); delete k; // zrušíme objekt

Pole smerníkov:

int i,*a[100]; // a je pole smerníkov na celé čísla for (i=0; iznak='a'; *Z->cislo=0; // tu niečo robíme ... delete Z->cislo; // najskôr uvoľníme dynamickú premennú, na ktorú ukazuje Z->cislo delete Z; // až potom uvoľnime dynamickú premennú, na ktorú ukazuje Z

Dynamické premenné nesmieme rušiť v takomto poradí:

delete Z; delete Z->cislo; ... lebo Z už ukazuje na neexistujúcu dynamickú premennú

Dynamicky vytvorené pole

V C++ môžeme pomocou operátora new vytvoriť aj viacero dynamických premenných rovnakého typu, ktoré ležia v pamäti za sebou, a teda tvoria pole. Pole, ktoré takto vznikne, nazveme dynamicky vytvorené pole: int i,*p; p=new int[10]; // vznikne 10 celočíselných premenných, ktoré sú v pamäti uložené za sebou - to je pole // premenná p ukazuje na 0. prvok poľa for (i=0; i