C++ - 10. lekce
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

C++ - 10. lekceC++ - 10. lekce

 

C++ - 10. lekce

Google       Google       16. 7. 2005       52 409×

  • alokace paměti pomocí operátoru new
  • uvolnění paměti pomocí operátoru delete
  • upozornění na práci s pamětí
  • úkol č.10

Reklama
Reklama

Nyní byste měli mít jistý pocit, jak ukazatelé pracují. Ovšem pojďme dále - alokování paměti za běhu programu.

Doposud jste inicializovali proměnné adresami proměnných. Co to jsou tedy proměnné? Pojďme si to zopakovat. Proměnné jsou pojmenovanou pamětí alokovanou v době kompilace. Ukazatele pouze poskytují druhé jméno pro paměť, ke které byste mohli přistupovat podle jména. K čemu tedy ukazatele? Pravá cena ukazatelů vyplouvá na povrch, když alokujete nepojmenovanou paměť na úschovu hodnot v době běhu programu. V tomto případě se k paměti dostanete pouze pomocí ukzatelů. Pokud jste se dříve učili C, mohli jste paměť alokovat pomocí f-ce malloc() - to stále můžete, ale C++ má lepší způsob - operátor new

Alokace paměti pomocí operátoru new

Takže jak na to?
Zkusíme si vytvořit nepojmenovanou paměť za běhu programu pro hodnotu typu int a budeme k ní přistupovat pomocí ukzatele. Poskytneme operátoru new typ dat, pro kterou chceme paměť, new nalezne blok správné velikosti a navrátí jeho adresu, tu přiřadíme ukazateli.

int * vek = new int

Tento příkaz říká programu, že chceme novou paměť vhodnou pro úschovu int. Jakmile ji nalezne, vrátí jeho adresu a ta se přiřadí do vek - což je typ ukazatele na int. Nyní je tedy vek adresou a * vek hodnotou uložené na dané adrese. Ukazatele se vám možná jeví nešikovně, ale máte větší pohled nad tím, jak váš program spravuje paměť. Ukažme si tedy obecný tvar:

jmeno_typu jmeno_ukazatele = new jmeno_typu

Poprvé určujete datový typ (int) požadované paměti a podruhé deklaraci vhodného ukazatele.


#include <iostream>
using namespace std;
int main()
{
  int * promenna = new int; // alokuje prostor pro int
  *promenna = 1001; // uloží tam hodnotu
  cout << "int hodnota = " << *promenna << ": umisteni = "
  << promenna << "
";
  double * promenna2 = new double; // alokuje prostor pro double
  *promenna2 = 10000001.0; // uloží tam double
  cout << "double hodnota = " << *promenna2 << ": umisteni = " 
  << promenna2 << "
";
  cout << "velikost promenna = " << sizeof promenna;
  cout << ": velikost *promenna = " << sizeof *promenna << "
";
  cout << "velikost promenna2 = " << sizeof promenna2;
  cout << ": velikost *promenna2 = " << sizeof *promenna2 << "
";
  cin.get();
  return 0;
}
A výsledek :

int hodnota = 1001: umisteni = 00420750
double hodnota = 1e+007: umisteni = 00420710
velikost promenna = 4: velikost *promenna = 4
velikost promenna2 = 4: velikost *promenna2 = 8

Ukazatele promenna a promenna2 ukazují na dva datové objekty - bez nich nemůžete k tmto paměťovým lokacím přistupovat. Zde také vidíme, proč musíme deklarovat typ, na který ukazatel ukazuje. Adresa odhalí jen začátek, kde je objekt uložen - jak vidíte, velikost ukazatele na int i double je stejná. Ale protože jsme deklarovali typy ukazatelů, program ví, že promenna2 má 8 bajtů.

Mimo rozsah paměti?
Pokud počítač nemá dostatek volné paměti, vrací hodnotu 0* => prázdný ukazatel. C++ zaručuje, že prázdný ukazatel nikdy neukazuje na platná data, takže se často používá na indikování selhání operátorů či f-cí, které jinak navracejí nepoužitelné ukazatele.

* pan Mirek Virius doplňuje:
Podle standardu ISO 14882-2003 operátor new v základní podobě nevrací při neúspěchu 0, ale vyvolává vyjímku ntypu std::bad_alloc. Chceme-li, aby vracel 0, musíme použít podobu new(nothrow) (a předtím uvést #include).

Možná stále nerozumíte - "proč bych měl používat něco, co je zbytečné, těžké... proč bych měl pracovat s nepojmenovanou pamětí, když můžu jednoduše pracovat s proměnnou?"
Odpověď je jednoduchá - klasické proměnné alokují paměť v době kompilace, kdežto alokovaná paměť pomocí operátoru new se alokuje ZA běhu programu - tedy pouze tehdy, pokud bude využita, potřebná... Klasická proměnná se vždy "přihlásí" o své místo na začátku běhu programu. Ale co když nepotřebujete tolik proměnných? Co když se ukáže, že některé proměnné nebudou za celý běh programu ani jednou využity? Myslíte si, že to není možné? A co podmínky? Jestliže uživatel zadá ano, provede se určená část programu. Takže možnost "ne" zůstane neupotřebena a veškerý následující kód po této podmínce nebude upotřeben - ani proměnné. Tedy zbytečně jste plýtvali místem. Kdežto při alokaci paměti během programu se vám toto nestane - paměť se alokuje pouze tehdy, je-li to nutné. Možná si říkáte, proměnné jsou jednodušší..., ale vy si nemůžete poté u složitějších programů plýtvat pamětí!! Určitě vás u nových her štve, že mají takové hardwarové nároky. Takže neučte se zavrhovat a odsuzovat alokoci paměti za běhu programu, naopak, naučte se to používat. No a proč tedy ukazatele? No přeci proto, abyste nějak mohli s danou pamětí pracovat. Tedy:
Pojmenovaná paměť - int a - můžeme se na ní odkázat jménem proměnné nebo ukazatelem na proměnnou.
Nepojmenovaná paměť - int vek = new int - můžeme se na ni odkázat pouze ukazatelem

Uvolnění paměti pomocí operátoru delete

Mysleli jste si, že alokujete paměť za běhu programu a konec? Ne, tak jednoduché to není. Klasická proměnná je po ukončení programu zničena (uvolněna), ale paměť alokovaná za běhu programu zůstává i nadále po ukončení progrmu alokována, není uvolněna!

Pamatujte, takto alokovanou paměť (pomocí operátoru new) VŽDY uvolněte pomocí operátoru delete!

Takto uvolněná paměť může být poté znova použita jinou částí vašeho programu. Jedná se o nejefektivnější využití paměti.


int * promenna = new int;   //alokace paměti pomocí new
delete promenna;   //uvolnění paměti pomocí delete

Toto odstraňuje paměť, na kterou ukazuje promenna, neodstraňuje to samotný ukazatel. Můžete ho znovu použít, aby ukazoval na jinou lokaci. Dále byste se neměli pokoušet uvolňovat blok paměti, který jste již uvolnili - výsledek není definován.


int * promenna = new int;   //ok
delete promenna;   //ok
delete promenna;   //chyba - již uvolněná paměť
int vek = 5;   //ok
int * cil = & vek;   //ok
delete cil;   //chyba - paměť nebyla alokována pomocí new

Upozornění:
Používejte delete pouze k uvolnění paměti alokované pomocí new a zapamatujte si, že je bezpečné aplikovat delete na nulový ukazatel.

Rozhodujícím testem na použití delete je to, že ho použijete na paměť alokovanou pomocí new. To znamená, že nepotřebujete použít stejný ukazatel k uvolnění paměti, který jste použili u new:


int * promenna = new int;   //alokuje paměť
int * prom = promenna;   //nastavuje druhý ukazatel na stejný blok
delete prom;   //uvolníte paměť pomocí druhého ukazatele

Obyčejně dva ukazatele na stejný blok paměti nechcete vytvořit, protože tím vzrůstá pravděpodobnost, že se chybně pokusíte uvolnit stejný blok 2×. Ale jak brzy uvidíte, použití druhého ukazatele má smysl, když pracujete s f-cí, která navrací ukazatel.

Úkol č.10

Bude lehký - alokujte 2× int, 1× double a 1× float(ne jako proměnné, ale pomocí operátoru new), nechte do nich uživatele zadat hodnoty a poté se ho zeptejte, zda bude potřebovat danou paměť, pokud ne, paměť se uvolní, pokud ano, nabídnete mu přepsání stávajících hodnot. A tak dokola, dokud uživatel neuzná data za zbytečná a dá uvolnit. Jakmile dá uvolnit, vypíšou se napsaná čísla. Budete tedy muset čísla nakopírovat do klasických proměnných.

V příští lekci se naučíte vytvářet dynamická pole pomocí operátoru new a jejich použití.

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Lukáš ChurýLukáš je šéfredaktorem Programujte, vyvíjí webové aplikace, fascinuje ho umělá inteligence a je lektorem na FI MUNI, kde učí navrhovat studenty GUI. Poslední dobou se snaží posunout Laser Game o stupeň výše a vyvíjí pro něj nové herní aplikace a elektroniku.
Web     Twitter     Facebook     LinkedIn    

Nové články

Obrázek ke článku NEWTON Media prohledá 200  milionů mediálních zpráv během sekund díky Cisco UCS

NEWTON Media prohledá 200 milionů mediálních zpráv během sekund díky Cisco UCS

Česká společnost NEWTON Media provozuje největší archiv mediálních zpráv ve střední a východní Evropě. Mezi její zákazníky patří například ministerstva, evropské instituce nebo komerční firmy z nejrůznějších oborů. NEWTON Media rozesílá svým zákazníkům každý den monitoring médií podle nastavených klíčových slov a nabízí online službu, kde lze vyhledat mediální výstupy v plném znění od roku 1996.

Reklama
Reklama
Obrázek ke článku Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Touto roční dobou, kdy je zem pokrytá barevným listím a prsty křehnou v mrazivých ránech, se obvykle těšíme na zbrusu novou verzi RAD Studia. Letos si však ale budeme muset počkat na Godzillu a Linux až do jara. Vezměme tedy za vděk alespoň updatem 2 a jelikož dle vyjádření pánů z Embarcadero se budou nové věci objevovat průběžně, pojďme se na to tedy podívat.

Obrázek ke článku Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Stále rostoucí zájem o cloudové služby i maximální důraz na pružnost, spolehlivost a bezpečnost IT vedou k výrazným inovacím v datových centrech. V infrastruktuře datových center hraje stále významnější roli software a stále častěji se lze setkat s hybridními přístupy k jejich budování i provozu.

Obrázek ke článku Konference: Mobilní technologie mají velký potenciál pro byznys

Konference: Mobilní technologie mají velký potenciál pro byznys

Firmy by se podle analytiků společnosti Gartner měly  rychle přizpůsobit skutečnosti, že mobilní technologie už zdaleka nejsou horkou novinkou, ale standardní součástí byznysu. I přesto - nebo možná právě proto - tu nabízejí velký potenciál. Kde tedy jsou ty největší příležitosti? I tomu se bude věnovat již čtvrtý ročník úspěšné konference Mobilní řešení pro business.

Reklama autora

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý