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.
