Nezabudnite na pamäť
V minulom článku sme rozoberali, ako môže funkcia vrátiť pointer ako návratovú hodnotu. Avšak sme zabudli rozobrať jednú dôležitú záležitosť a to pamäť. Priznám sa bez mučenia, že som si v zmienenom článku neuvedomil nutnosť ošetrenia pamäte pre pointer. Aspoň sa môžete poučiť z mojej chyby. Poďme si ukázať jednoduchý príklad, na ktorom budeme demonštrovať tento kritický problém.
#include <iostream> using namespace std; int* scitaj(int cislo1, int cislo2) { int vysledok = cislo1 + cislo2; int *ptr=&vysledok; return ptr; } int main() { int volba1,volba2; cout << "Zadajte prve cislo, ktore chcete scitat od 1 do 99: "; cin >> volba1; if(volba1 < 1 || volba1 > 99) { cout << "Nepripustna operacia\n"; return 0; } cout << "Zadajte druhe cislo, ktore chcete scitat od 1 do 99: "; cin >> volba2; if(volba2 < 1 || volba2 > 99) { cout << "Nepripustna operacia\n"; return 0; } int *num=scitaj(volba1,volba2); cout << "Vysledok scitania cisiel "<<volba1<< " a " <<volba2<<" je: "<<*num<<"\n"; return 0; }
Výsledok programu:
Zadajte prve cislo, ktore chcete scitat od 1 do 99: 44 Zadajte druhe cislo, ktore chcete scitat od 1 do 99: 79 Vysledok scitania cisiel 44 a 79 je: 123
Ak tento program spustíte, tak v drvivej väčšine vám vypíše správny výsledok. Avšak, zdanie klame. Chyba pramení v tom, že my sme deklarovali lokálnu premennú vo funkcii, ktorá prestane existovať skončením bloku funkcie. To, že dostaneme správny výsledok výpočtu, je vecou kompilátora. Ak by sme mali zložitejší program s mnohými premennými, tak by došlo k deklarácii inej premennej v pamäťovom priestore pôvodnej lokálnej premennej.
Skúsme teraz pointeru vyhradiť pamäť s pomocou new int
. Čiže pointer nebude odkazovať na lokálnu premennú, ale na nový pridelený blok pamäte o veľkostí zvoleného typu premennej. Potom už nám nič nebráni v tom, aby sme priradili hodnotu do pointeru odkazujúceho na vyhradený blok pamäte.
#include <iostream> using namespace std; int* scitaj(int cislo1, int cislo2) { int vysledok = cislo1 + cislo2; int *ptr = new int; *ptr=vysledok; return ptr; } int main() { int volba1,volba2; cout << "Zadajte prve cislo, ktore chcete scitat od 1 do 99: "; cin >> volba1; if(volba1 < 1 || volba1 > 99) { cout << "Nepripustna operacia\n"; return 0; } cout << "Zadajte druhe cislo, ktore chcete scitat od 1 do 99: "; cin >> volba2; if(volba2 < 1 || volba2 > 99) { cout << "Nepripustna operacia\n"; return 0; } int *num=scitaj(volba1,volba2); cout << "Vysledok scitania cisiel "<<volba1<< " a " <<volba2<<" je: "<<*num<<"\n"; return 0; }
Výsledok programu:
Zadajte prve cislo, ktore chcete scitat od 1 do 99: 71 Zadajte druhe cislo, ktore chcete scitat od 1 do 99: 25 Vysledok scitania cisiel 71 a 25 je: 96
No fajn, ale čo ak máme v programe mnoho premenných a bez uvoľnenia pamäte už nevyužívaných premenných sa nám rýchlo spotrebuje pamäťový priestor? Preto je dobrým zvykom uvoľniť pamäť, ak ju už nepotrebujeme. Nato nám slúži príkaz delete
. V našom jednoduchom príklade ho prakticky pridáme na konci programu. To ale neznamená, že v zložitejšom programe budete uvoľňovať pamäť až na konci programu. Vždy musíte zvážiť, kedy už nepotrebujete využívať premennú a tak s pomocou príkazu delete
získate cenný pamäťový priestor.
#include <iostream> using namespace std; int* scitaj(int cislo1, int cislo2) { int vysledok = cislo1 + cislo2; int *ptr = new int; *ptr=vysledok; return ptr; } int main() { int volba1,volba2; cout << "Zadajte prve cislo, ktore chcete scitat od 1 do 99: "; cin >> volba1; if(volba1 < 1 || volba1 > 99) { cout << "Nepripustna operacia\n"; return 0; } cout << "Zadajte druhe cislo, ktore chcete scitat od 1 do 99: "; cin >> volba2; if(volba2 < 1 || volba2 > 99) { cout << "Nepripustna operacia\n"; return 0; } int *num=scitaj(volba1,volba2); cout << "Vysledok scitania cisiel "<<volba1<< " a " <<volba2<<" je: "<<*num<<"\n"; delete num; return 0; }
Uvoľnenie pamäte dosiahneme príkazom delete num;
. Upozornenie, uvoľniť pamäť môžete len pri dynamicky pridelenej pamäte s pomocou operátora new
. Zároveň ak na pridelenú pamäť ukazuje viacero pointerov, stačí uvoľniť pamäť cez jeden pointer.