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ť:
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