|
|||||||||||||||||||||||||||||||||||||||||||||||||
Menu
Distributions (131)
bootable [55]
commercial [7] no-commercial [42] unclassified [20] [7]
Software (10844)
|
C++ a garbage collectorČasto se mluví o tom, že C++ nemá garbage collector. Jenže ona to, přísně vzato, není ani trochu pravda. Už mnoho let tvrdím, že kdo v C++ ručně uvolňuje paměť a zavírá různé zdroje, ten neumí C++. Tento článek filozofuje s otázkou, zda C++ má či nemá garbage collector.
1. C++ a garbage collector1.1. C++ není C s třídamiJedna z nejhorších věcí, které může člověk dělat je, že chce předělávat jazyk či knihovnu k obrazu svému do cizí filozofie. Řada lidí posuzuje C++ jako C s třídami a přisuzují mu tytéž vlastnosti jako jazyku C. Jistě, že v C++ se dá programovat C stylem, ale je to obrovská škoda, protože C++ nabízí mnohem mnohem více. Využít možnosti C++ znamená v první řadě zapomenout C styl a nedělat věci v C++ tak, jak by je člověk dělal v C. Pokud programujete v C++, využívejte jeho možností. C++ je velmi efektivní jazyk, umožňující mnohem efektivnější a rychlejší vývoj, než v C, aniž byste ztratili jedinou výhodu proti jazyku C. V C++ lze napsat program mnohem rychleji a efektivněji, než v C, přitom výsledek bude mnohem lépe udržovatelnější zdrojový kód oproti C a výsledná binárka bude stejně rychlá jako kdyby byla napsána v C. Abyste tohoto dosáhli, je třeba využívat možností a vlastností C++. Kdokoli má pocit, že C++ je pouze C s třídami, neříká tím o sobě nic jiného, než „já neumím C++“. 1.2. Cíle článkuV tomto článku se pokusím jednoduše zodpovědět na 3 otázky:
2. Má C++ garbage collector pro automatické uklízení paměti?Správná odpověď je: Přijde na to. C++ umožňuje vytvářet pointery, které jsou plně na zodpovědnosti programátora. A které programátor uklízí ručně a plně na své triko. C++ umožňuje vytvářet pointery i objekty, které se automaticky dealokují a uklízejí bez starosti programátora. Takže na otázku „Je pravdou, že C++ nemá garbage collector?“, nelze poctivě odpovědět, že C++ nemá garbage collector. 2.1. Návrhový vzor RAIIProgramovací jazyk C++ pracuje na principu, že samotný C++ kompilátor velmi masivně už na úrovni jazyka C++ podporuje objektový návrhový vzor RAII (Resource Acquistion Is Initialization), nazývaný také SBRM (Scope Based Resource Management). Tento objektový návrhový vzor řídí životnost objektů, proto patří to do skupiny „creational patterns“. Ve své podstatě je to vlastně „cé plus plus kovina“, protože je v ní cítit přesně ideologie C++. Tedy zobecňování principů až do maximální rozsahu, působení a důsledků, jaký je možný. Dokonce právě uvědomění si základní vlastnosti programovacího jazyka C++, tedy, že se skládá v zásadě z několika jednoduchých základních principů a vlastností, které jsou dotáhnuté až do maxima, považuji za nejlepší způsob, jak se bezbolestně naučit C++. Pokud v C++ platí nějaký princip či vlastnost, pak pokud možno platí všude, na všechny typy i programátorské konsktrukce, kde je to jen trochu možné. Té vlastnosti říkám „cé plus plus kovina“, tedy obrovská vnitřní konzistence, logičnost a jednotnost celého C++ jazyka. Učit se C++ jinak, než pochopením jeho principů je velmi složité, učit se C++ pochopením jeho principů je velmi jednoduché a rychlé. 2.2. C++ dotahuje princip uklízení lokálních proměnných do absolutní dokonalostiČlověk očekává, že ukončením podprogramu (či bloku programu) se automaticky odstraní a uklidí i lokální proměnné bez starostí programátora. Toto je ovšem ve většině programovacích jazyků nedotáhnuté, a není tomu plně tak. Vezmete-li si třeba Javu, .NET, C a mnoha dalších jazyků, nemůžete od nich očekávat to, že kompilátor zařídí také plný úklid lokálních proměnných. Uklízí se bez problémů proměnné typu integer, ale ne objekty. C++ dotáhl uklízení lokálních proměnných na plný automatický úklid a to pro jakékoli proměnné jakéhokoli typu. Tohle dotahování do konce je vlastně to, čemu říkám „cé plus plus kovina“, protože takto vzniklo skoro celé C++. Dotáhnutím principů do konce bez výjimek a nedotažeností. Zaručený automatický úklid všech lokálních proměnných se právě nazývá RAII. Jednoduše stačí získat zdroj (paměť, soubor, grafický handle, cokoli) a uložit ho do proměnné, která ho bude vlastnit a při jejím zániku (voláním destruktoru) ho také uvolní. A tím se o to můžete přestat starat, protože zbytek zařídí C++ kompilátor, který bude uvolňovat zdroje automaticky v rámci rušení lokálních proměnných na konci oboru platnosti. A tomu se vznešeně říká RAII. 2.3. RAII versus klasický garbage collectorAčkoli to vypadá jako nic moc, RAII je skutečně velmi dobrý garbage collector. Dokonce má další výhody:
Má samozřejmě i nevýhody:
2.4. C++ a uklízení sdílených proměnnýchDobrá, RAII tedy zruší již nepoužívanou paměť a zdroje lokálních proměnných. Ale co tedy uklízení paměti a zdrojů sdílených více tready nebo vranými jako návratové hodnoty? Budete se divit, toto RAII také zvládne. Protože všechny případy automatického uklízení paměti se dají převést na uklízení lokálních proměnných. Kdy je třeba paměťový blok dealokovat? Když pointer na tento blok není obsažen v žádné proměnné, míněno v žádné lokální proměnné. Jakmile neexistuje lokální proměnná, která obsahuje adresu nějakého paměťového bloku, pak je třeba tento blok uklidit. A toto je možné pomocí RAII zařídit. Nicméně zde je třeba použít chytré pointery z C++ standardní knihovny nebo podobnou funkcionalitu. Například std::auto_ptr nebo std::shared_ptr. Případně si napsat vlastní třídy. Není tedy problém mít (jde o myšlenkový nástin, skutečný kód by byl odlišný): MojeTrida * JinaTrida::getInfo() { … }; int main() { JinaTrida a; a.getInfo(); int x = a.getInfo()->getXParameter(); MojeTrida * info = a.getInfo(); int y = info->getYParameter(); return 0; }; A ačkoli se o to nestaráte, ve funkci main() nevznikne žádný memory leak, všechna paměť se uklidí a všechny instance třídy MojeTrida, které jsou vráceny metodou getInfo() budou automaticky uklizeny hned jak nebudou potřeba. Jinak řečeno, v C++ opravdu je možné vracet z funkcí a metod pointery na objekty, a nechat C++ jejich automatické uklízení, aniž byste se o uklízení starali ručně. 2.5. C++ a garbage collectingZnovu se ptám: „Má nebo nemá C++ garbage collector?“ Jak vidíte, odpovědět jde opravdu těžko. Oficiálně nemá, prakticky ale obsahuje věkerou funkčnost garbage collectoru, když o to budete stát a budete to potřebovat. Už 10 let tvrdím, že pokud se v C++ někdo musí starat ručně o uvolňování paměti, tak neprogramuje v C++, protože ho neumí. 3. Potřebuje C++ klasický garbage collector?V každém jazyce je dobré mít možnost garbage collectoru, jde-li to. Garbage collector je příjemná feature. Na druhé straně garbage collector nemá jenom plusy. 3.1. Klasický garbage collectorGarbage collectorů je mnoho druhů, klasický garbage collector funguje na principu procházení všech identifikátorů v programu a uklízí pak ty bloky paměti, na které nevede žádný odkaz. A zde je kámen úrazu. Těžko bude garbage collector zjišťovat a procházet identifikátor, když program běží a identifikátory mění své hodnoty, protože programu musí stát a násilně být zastaven. A to se velmi často nehodí, přesněji, nehodí se to skoro nikdy. Pokud program dělá rychlostně kritickou činnost, pak garbage collector na chvíli zastavující program je poslední ranou do vazu. Ale i jinak, uživatel není rád, když program sekundu nereaguji na jeho kliknutí na tlačítko, protože zrovna se probral gc. To se různě eliminuje, ale je to jen zmírnění problému, nikoli jeho odstranění:
Toto nejsou všechny problémy klasického gc. Další problém je uvolňování zdrojů. Gc se postará o uvolňování paměti, ale už ne dalších zdrojů. Programátor se o to musí starat ručně, pokud nemá docházet k plýtvání zdroji. A tak se to zase řeší nalepováky:
3.2. Garbage collector typu čítač referencíCílem článku není kritizovat klasický garbage collector. Existují i gc, které uvolňují okamžitě a většinu výhod výše eliminují. Například čítač odkazů. Jenže ten má další nevýhody:
3.3. C++ a potřeba garbage collectoruC++ jednoduše takové garbage collectory opravdu nepotřebuje. Jednoduše proto, že oblast používání C++ je tam, kde by vlastnosti klasického garbage collectoru či čítače referencí zničily to, co od C++ je žádáno. Namísto toho proto C++ integrovalo RAII, které udělalo přesně to, co je třeba:
4. Je účelné vybavit C++ garbage collectorem?Tato otázka už je mírně nadbytečná. C++ má už v samotném jazyce vše potřebné pro automatické uklízení paměti a zdrojů v podpoře RAII. Jako vždy, C++ pouze nabízí, ale nevnucuje. Můžete klidně dělat program, kde budete celý životní cyklus paměti i zdrojů řídit sami, stejně jako můžete udělat program, kde uklízení bude probíhat zcela automaticky. Článek daroval: Ing. Miloslav Ponkrác
Related article
C/C++ (1) - Úvod C/C++ (2) - První program C/C++ (3) - Proměnné a konstanty C/C++ (4) - Funkce printf C/C++ (5) - Funkce printf podruhé C/C++ (6) - Operátory C/C++ (7) - Podmínka C/C++ (8) - Cykly C/C++ (9) - Pole C/C++ (10) - Standardní vstup a výstup C/C++ (11) - Čtení a konverze čísel C/C++ (12) - Preprocesor C/C++ (13) - Preprocesor podruhé C/C++ (14) - Funkce C/C++ (15) - Proměnné C/C++ (16) - Hlavičkové soubory C/C++ (17) - Makefile C/C++ (18) - Makefile podruhé C/C++ (19) - Příkaz switch a bitové operátory C/C++ (20) - Alokace paměti C/C++ (21) - Práce s řetězci C/C++ (22) - Struktury C/C++ (23) - Seznam C/C++ (24) - Soubory C/C++ (25) - Funkce s proměnným počtem parametrů C/C++ (26) - Standardní knihovna C/C++ (27) - Standardní knihovna podruhé C/C++ (28) - Standardní knihovna potřetí C/C++ (29) - Standardní knihovna počtvrté C/C++ (30) - Výčtový typ a nestandardní knihovny C/C++ (31) - Jazyk C++, historie, charakteristika, vztah k C C/C++ (32) - Omezení C++ oproti C C/C++ (33) - Rozdíly mezi C a C++ C/C++ (34) - Drobná vylepšení C++ C/C++ (35) - Reference, funkce C/C++ (36) - Prostory jmen C/C++ (37) - Prostory jmen podruhé C/C++ (38) - Prostory jmen potřetí C/C++ (39) - Objektově orientované programování C/C++ (40) - Dědičnost a virtuální metody GCC vs. CLANG C++ Binární vyhledávací stromy C++ Datová struktura zásobník C++ - Hashování C++ - Vyhledávání v textu - Brute Force algoritmus C++ šablony Grafy a grafové algoritmy I Grafy a grafové algoritmy II C++ výjimky C++ Funktory neboli funkční objekty Grafy a grafové algoritmy III. Previous Show category (serial)
|
Szukanie oprogramowania
|
|||||||||||||||||||||||||||||||||||||||||||||||
©Pavel Kysilka - 2003-2024 | maillinuxsoft.cz | Design: www.megadesign.cz |