Generatı v programok helyesse ge

Méret: px
Mutatás kezdődik a ... oldaltól:

Download "Generatı v programok helyesse ge"

Átírás

1 Generatı v programok helyesse ge Doktori e rtekeze s 2013 Pataki Norbert patakino@elte.hu Te mavezeto : Dr. Porkola b Zolta n, egyetemi docens Eo tvo s Lora nd Tudoma nyegyetem, Informatikai Kar, 1117 Budapest, Pa zma ny Pe ter se ta ny 1/C ELTE IK Doktori Iskola Doktori program: Az informatika alapjai e s mo dszertana Az iskola vezeto je: Dr. Benczu r Andra s A program vezeto je: Dr. Demetrovics Ja nos akade mikus A projekt az Euro pai Unio ta mogata sa val, az Euro pai Szocia lis Alap ta rsfinanszı roza sa val valo sul meg (a ta mogata s sza ma TA MOP4.2.1./B-09/1/KMR ).

2 Tartalomjegyzék I. Bevezetés 5 I.1. Célkitűzések I.2. A dolgozat felépítése II. Alapok 9 II.1. Sablonok C++-ban II.2. Generatív és generikus programozás II.3. A C++ Standard Template Library II.4. Motivációs példák II.4.1. Fordítási hibaüzenetek II.4.2. Invalid iterátorok II.4.3. Funktorokkal kapcsolatos hibák II.4.4. Allokátorokkal kapcsolatos hibák II.4.5. Másoló algoritmusokkal kapcsolatos hibák II.4.6. Törlő algoritmusokkal kapcsolatos hibák II.4.7. A unique algoritmus II.4.8. Algoritmusok speciális előfeltételei II.4.9. A find és a count algoritmus II A vector<bool> konténer II COAP II Fejállományokkal kapcsolatos problémák II Iterátorok konverziója II Az asszociatív konténerek hordozhatósággal kapcsolatos problémái II A vector és a string reallokációja II Iterátorok és pointerek összetévesztése II Virtuális destruktorok hiánya III. Az STL formális megközelítése 54 III.1. A Hoare-módszer bővítése III.1.1. A Hoare-módszer

3 Tartalomjegyzék 3 III.1.2. A formalizmus bővítése III.1.3. Specifikációk III.1.4. Példák III.2. LaCert III.3. Összegzés IV. Fordítás idejű megoldások 75 IV.1. Warning-ok generálása IV.2. Hibás példányosítások IV.2.1. A vector<bool> konténer IV.2.2. COAP IV.3. Algoritmusok IV.3.1. Az iterator traits kibővítése IV.3.2. Másoló algoritmusok IV.3.3. A count és a find algoritmus IV.3.4. A unique algoritmus IV.4. Adaptálható funktorok IV.5. Allokátorok IV.6. Reverse iterátorok IV.7. Lusta példányosítás IV.8. Összegzés V. Futási idejű megoldások 102 V.1. Az iterator traits kibővítése V.2. Invalid iterátorok V.3. Másolás-biztonságos iterátorok V.4. Törlő iterátorok V.5. Algoritmusok előfeltétele V.6. Funktorok V.7. Összegzés VI. Összefoglalás 118 A. Az STL bővítése a C++11-ben 132 A.1. Konténerek A.2. Algoritmusok A.3. Iterátorok

4 Köszönetnyilvánítás Legelőször szeretném témavezetőmnek, Porkoláb Zoltánnak (gsd-nek) megköszönni a sokéves témavezetői munkáját! A közös munkánk nagyon sokat jelent nekem. Még a unique-ot is legyőztük! Köszönöm páromnak, Melindának, hogy megteremtette az otthonunkat, ahol kényelmesen dolgozhattam, támogatott és gondosan lektorálta a cikkeket és a disszertációmat. Még nagyon hosszú a lista, nem szeretnék senkit sem kihagyni, de szeretném megköszönni a családomnak, a barátaimnak és a munkatársaimnak a kitartó támogatást. A szerzőtársaimnak köszönöm a munkát, amit a közös cikkekbe öltek. 4

5 I. fejezet Bevezetés A programozás történetének elmúlt ötven évében egyre bonyolultabb és öszszetettebb alkalmazások születtek. Ahogy a szoftverek egyre komplexebbé váltak, a fejlesztőknek egyre több implementációs részlettel kellett foglalkozniuk. Felmerült az igény arra, hogy a rendszeresen használt kódrészleteket ne kelljen újra és újra megírni, hanem azok külső egységekként átvihetők legyenek akár különböző alkalmazások között is. Az ilyen elven megvalósított szoftver egységeket nevezzük könyvtáraknak (library). Kezdetben, a procedurális paradigma szemléletének megfelelően, a függvénykönyvtárak terjedtek el. Alprogramok (függvények, eljárások) segítségével előre megírtak olyan funkcionalitásokat, amelyeket később különböző paraméter értékekkel számos környezetben meghívhattak. Például FORTRANhoz vagy C-hez számtalan ilyen elven működő könyvtár elérhető. Az objektum-orientált programozás térhódításával együtt a könyvtárak felépítése is megváltozott. Függvénykönyvtárak helyett osztálykönyvtárakat implementáltak és használtak a programozók. Ekkor előre megírt osztályok, öröklődés és virtuális metódusok segítségével hoztak létre osztályhierarchiákon alapuló könyvtárakat, amelyek a korábbi megoldásokhoz képest jobban támogatták a kódújrafelhasználást. A Simula, Smalltalk, Eiffel és a Java programozási nyelvek elterjedésével ezek a könyvtárak széleskörben elfogadottá váltak. Az objektum-orientált könyvtáraknál még flexibilisebb megoldást nyújtanak a generikus könyvtárak. A konténerek és az algoritmusok függetlensége miatt ezek a rendszerek egyszerre több irányba bővíthetőek és feloldanak olyan problémákat, amelyeket régebbi megközelítéssel nem lehet kényelmesen kezelni. A C++ sablonok segítségével fordítási időben végrehajtódó kódokat is lehet írni, ezek a template metaprogramok. Léteznek metaprogramozási technikákon alapuló könyvtárak is [1, 104, 118]. Az aktív könyvtárak (active 5

6 6 Bevezetés libraries) olyan könyvtárak, amelyek fordítási időben dinamikusan viselkednek: döntéseket hoznak a felhasználás környezetének ismeretében, optimalizációkat végeznek fordítás közben, stb. [15]. A C++ Standard Template Library (STL) a generikus programozási paradigmán alapuló könyvtárak mintapéldája. Professzionális C++ program elképzelhetetlen a szabványkönyvtár részét képező STL alkalmazása nélkül. Az elegáns kialakítású könyvtár használata csökkenti a klasszikus C és C++ hibák lehetőségét, növeli a kód minőségét, karbantarthatóságát, érthetőségét és hatékonyságát [78]. Ugyanakkor a könyvtár alkalmazása nem garantál hibamentes kódot, sőt a könyvtár generikus megközelítése miatt új típusú hibalehetőségek keletkezhetnek. Ezeknek egy részét a fordítóprogram nem ellenőrzi és futási időben nem derül ki a kód hibás jellege. Bizonyos esetekben a hiba okát is nehéz felderíteni akár debugger alkalmazások segítségével is. Nem megdöbbentő, hogy ilyen hibák nagy számmal előfordulnak C++ nyelven írt programok implementációjában [53]. Kutatásaim középpontjában ezen hibalehetőségek leküzdése áll mégpedig úgy, hogy az STL hatékonysága és rugalmassága megmaradjon. I.1. Célkitűzések Kutatásaim kiindulópontja a [53] könyv volt, melyben 50 tanács található az STL helyes, hatékony használatáról. Ezek a tanácsok szövegesen (informálisan) írták le, hogy mit hogyan érdemes használni, mi milyen hibát okozhat. Többek között ilyen témák találhatók a könyvben: Részesítsük előnyben az intervallumokat használó tagfüggvényeket Használjuk az empty-t, a size == 0 vizsgálat helyett Használjuk a reserve-t, hogy elkerüljük a felesleges reallokációkat Fontoljuk meg az asszociatív tárolók cseréjét rendezett vector-ral Ismerjük a lehetőségeinket a rendezésekkel kapcsolatban Szoftveres megoldást nem kínál a könyv a tanácsokhoz, ezért azt a célt tűztem ki magam elé, hogy a programozók dolgát megkönnyítem az elkövethető hibák minél átfogóbb kiszűrésével. A szűrést segítsem mind formális, mind szoftveres eszközökkel. Egy kísérleti eszköz az STLlint [35], mely egy módosított fordítóprogram alapján működik, sokáig online elérhető volt,

7 Bevezetés 7 de működése nem váltotta be a hozzá fűzött reményeket, támogatása megszűnt. Az STLlint kizárólag fordítási idejű információk alapján működött. Az én megoldásaim ezzel szemben a könyvtár implementációjának bővítésén, változtatásán alapulnak, szabványos fordítóprogramok használata mellett. Én is igyekeztem a lehetséges hibákat fordítási időben felderíteni és a C++ sablon konstrukciója segítségével fordítási figyelmeztetéseket generálni, de a megoldásaim egy része futási időben működik. Tehát céljaimat a következő prioritással lehet definiálni: 1. Az STL generikusságából adódó hibalehetőségek kiszűrése fordítási időben, nem-intruzív módon. 2. Az STL generikusságából adódó hibalehetőségek kiszűrése fordítási időben, az STL implementáció módosításával. 3. Az STL generikusságából adódó hibalehetőségek kiszűrése futási időben, nem-intuzív módon, a szabványos aszimptotikus futási idők betartásával (törekedve a minimális overhead-re). 4. Az STL generikusságából adódó hibalehetőségek kiszűrése futási időben, az STL implementáció módosításával, a szabványos aszimptotikus futási idők betartásával (törekedve a minimális overhead-re). 5. Az STL generikusságából adódó hibalehetőségek kiszűrése futási időben, nem-intruzív módon, a szabvány aszimptotikus futási idő korlátainak megsértésével. 6. Az STL generikusságából adódó hibalehetőségek kiszűrése futási időben, az STL implementáció módosításával, a szabvány aszimptotikus futási idő korlátainak megsértésével. Emellett törekedtem a reverse-kompatibilitásra: meglévő (hibás) kódrészletek (legacy kódok) működhessenek az eredeti viselkedésnek megfelelően, hiszen nem lehet több millió kódsort hirtelen átírni például eddig nem ismert kivételek elkapására. Ha nem maradnék reverse-kompatibilis és például kivételeket dobnék hiba esetén, akkor rengeteg program abortálhatna le nem kezelt kivételek miatt. I.2. A dolgozat felépítése A dolgozat további fejezeteiben bemutatom a kutatásaimat, amelyekkel az STL használata biztonságosabbá tehető. A második fejezetben bemutatom a

8 8 Bevezetés generatív és generikus programozási paradigmát, részletezem az STL felépítését és a fontosabb részeit. Emellett példákat adok olyan kódokra, amelyek lefordulnak és hibás voltukat semmi sem fedi fel. A harmadik fejezetben bemutatom az általam kidolgozott eszközöket, amelyekkel az STL formálisan definiálható. A negyedik fejezetben olyan megoldásokat adok, amelyek fordítási időben elősegítik az STL hibás használatának kiszűrését a fordítóprogram módosítása nélkül. Az ötödik fejezetben olyan általam kidolgozott eszközöket részletezek, amelyek vagy futási időben jelzik az STL hibás használatát vagy leküzdik a hiba okát. Végezetül összefoglalom a dolgozat eredményeit. Kutatásaimat a 2003-as C++ szabvány szerint végeztem. Az azóta elfogadott C++11 szabvány kapcsolódó részeit a függelékben ismertetem.

9 II. fejezet Alapok II.1. Sablonok C++-ban A CLU programozási nyelv vezette be először azt a nyelvi konstrukciót, melylyel típussal paraméterezhetünk programegységeket. A parametrikus polimorfizmus legfontosabb eszköze lett a template vagy generic [115]. A C++ template-jei segítségével osztály- és függvénysablonok írhatóak, amelyek sablonparaméterekkel paraméterezhetőek: fordítási időben ismert értékű paraméterekkel láthatóak el. Ezen paraméterek ismeretében a fordítóprogram (compiler) képes példányosítani a sablont és generálni a konkrét függvényt vagy osztályt. Vizsgáljuk meg a következő függvénysablon példát: template <class T> const T& max( const T& a, const T& b ) return a < b? b : a; A kódrészlet két tetszőleges, de azonos típusú objektum közül adja viszsza a nagyobbat. Használható int-ekkel, double-ökkel, stb. minden olyan típussal lehet ezt a sablont használni, amelynek van operator< művelete. Látható, hogy ez az elvárás csak a sablon törzséből derül ki. A sablon önmagában nem használható, a fordítóprogram sem elemzi a kódot átfogóan, nem generálódik belőle alacsony-szintű kód. Példányosítani (instantiate) kell a használathoz. Példányosításkor a sablonból konkrét kód generálódik, amelyben a formális sablonparaméterek helyén az aktuális paraméterek szerepelnek. C++-ban a fordítóprogram képes a függvénysablonok esetében a hívás 9

10 10 Alapok paramétereiből levezetni a sablon paramétereket, ezt a nevezik paraméterdedukciónak (parameter deduction). Az általánosságnak hátránya is van, például nem definiált, hogy mit ír ki az alábbi kódrészlet: std::cout << max( "one", "ten" ); Ilyenkor a fordítóprogram a "one" és a "ten" literálok típusát egyaránt const char[4]-nek vezeti le. A tömbök konvertálódnak első elemre mutató pointerré, és a kódrészlet két független tömb első elemére mutató pointert hasonlít össze, melynek eredménye nemdefiniált. Ha lexikografikus rendezést szeretnénk használni, akkor a függvénysablon explicit specializációját alkalmazhatjuk: std::cout << max<std::string>( "one", "ten" ); A C++ osztálysablonok esetében lehetőséget ad felhasználói specializációra is [111]. A specializációnak két fajtája van: részleges és teljes. A részleges specializáció esetében egy eltérő implementáció léphet életbe, ha egy típus csoport valamely tagjával példányosítjuk a sablont. A teljes specializáció esetében egy eltérő implementáció léphet életbe, ha egy konkrét típussal példányosítjuk a sablont. Nézzük meg az alábbi példát: 1 template <class T> 2 class Foo 3 4 //... 5 ; 6 7 template<class T> 8 class Foo<T*> 9 10 // ; template <> 14 class Foo<bool> // ; Foo<char> a; // 1-5 sorok példányosítása

11 Alapok Foo<bool*> b; // 7-11 sorok példányosítása 21 Foo<bool> c; // sorok példányosítása A különböző sablonparaméterek miatt eltérő implementációt használnak a különböző objektumok. A specializációk más belső reprezentációt használhatnak, sőt a publikus interface-ük is eltérő lehet. Mivel a sablon paraméterek fordítás idejű paraméterek, így az, hogy melyik specializációt alkalmazzuk fordítási időben kiderül. A sablonok specializációi egy újfajta megközelítést hoztak a C++ nyelvbe. Segítségükkel fordítási időben futó kódrészletek hajthatóak végre, ezeket nevezzük template metaprogramoknak [1]. A metaprogramokat funkcionális megközelítéssel kell megírni: csak a rekurzív példányosításokra és specializációkra számíthatnak a programozók, nincsenek más vezérlési szerkezetek. A metaprogramok résznyelve Turing-teljes, de a valódi korlátai a mai napig kutatott terület [84]. A metaprogramok tipikus alkalmazásai: extra fordítás-idejű ellenőrzések, algoritmusok végrehajtása, a futás-idejű programok optimalizációi, domain-specifikus nyelvek definiálása. A metaprogramok alanya maga a C++ program. A metaprogramok lehetősége a C++ sablonjait egy rendkívül fontos konstrukcióvá teszi. A max sablon függvénynél már említettem, hogy a sablonparaméterekkel kapcsolatos elvárások kizárólag az implementációban jelennek meg, a deklarációban semmilyen információ nem szerepel ezzel kapcsolatban. Ha olyan típussal használjuk, amelynek nincs operator< művelete (pl. komplex számok kezeléséhez használt std::complex<double>), akkor a fordítóprogram példányosítja a sablont és példányosított kód fordításakor realizálja, hogy a kód nem lefordítható és hibaüzenet ad, amelyben a sablonra hivatkozik. A fordítóprogramok jelzik, hogy milyen aktuális sablonparaméterek mellett jött elő a hiba, de nem a példányosítást jelzik a hiba okaként. Ennek a jelenségnek az az oka, hogy a C++ sablonjai megszorítás nélküliek (unconstrained). Ez tervezési tulajdonsága a C++ sablonjainak [26]. Ez a tervezési tulajdonság biztonságos abból a szempontból, hogy hibás példányosítás esetében fordítási hibaüzenetet kap a programozó, nem jön létre hibásan futó program. Ugyanakkor sokszor bonyolult, nehezen érthető hibaüzenetekkel jár a megszorítás nélküli sablonok hibás használata. Ezért a kutatók elkezdtek metaprogramozási alapokkal ellátott könyvtárakat implementálni, amivel a fordítás korábbi pontján kiderülnek a hibás példányosítások. Sajnos azonban ezek a könyvtárak nem tudnak minden problémát kezelni, ezért a kutatók nyelvi bővítést szorgalmaztak a könyvtár-alapú megoldásokkal szemben [31]. Az új C++ nyelvi konstrukciót, a concept-et két eltérő formában képzelték el: a University of Texas A&M [95] és az Indiana University [39]

12 12 Alapok kutatói. A konstrukciók közös lényege, hogy típusmegszorítások definiálhatóak legyenek a C++ sablonparaméterein, oly módon, hogy megtartsák a C++ sablon rendszerének előnyeit. A két eltérő verziót egységessé formálták [33], implementációs technikákat dolgoztak ki [34, 37, 38] és egy kísérleti fordítóprogramot (ConceptC++) implementáltak, hogy gyakorlatban is ki lehessen próbálni az ötleteket. A concept lett a leginkább várt nyelvi bővítés az új C++ szabványban, miután 2008-ban beszavazták a C++0x-be. Stroustrup egy eltérő, egyszerűsített concept fogalmat definiált [94], aminek az lett a következménye, hogy 2009 nyarán a Szabványosítási Bizottság úgy döntött, hogy az új C++ szabványban mégsem lesz benne a concept konstrukció. Nem csak típusok lehetnek sablonparaméterek. C++-ban integrális konstansok (pl. int-ek, bool-ok, char-ok, stb.), mint fordítási idejű adatok, szintén átadhatóak sablonparaméterként. Osztálysablonok esetében lehetőség van default sablonparaméterek megadására is. Az ilyen paramétereket objektumok típusának megadásakor nem kötelező megadni, ha nincs megadva, akkor a default paraméterek lépnek életbe. A sablonok alkalmazásával nagymértékben növelhető a programok biztonsága. A dolgozatban részletesebben tárgyalt témák mellett az alábbi kutatásokat folytattam C++ template-kkel kapcsolatban. Megvizsgáltam egy template metaprogramozás alapú tesztelési keretrendszer lehetőségét [62]. A cikkben megmutattam, hogy számos előnnyel járhat egy olyan tesztelési keretrendszer, ahol a futási idejű programokat metaprogramok segítségével teszteljük. A metaprogramozás terjedését jelentősen hátráltatja a szokásos programfejlesztői eszközök hiánya. Részt vettem egy grafikus metaprogram debugger és olyan vizualizációs eszköz kidolgozásában, amely bemutatja a példányosítás folyamatát kép file-okba kiexportált gráfok formátumában. Ezek az eszközök nagymértékben elősegítik a programozói hibák kijavítását és elkerülését [8, 74]. Különböző objektum-orientált nyelvek eltérően támogatják a paradigmát, minden nyelv kicsit eltérő konstrukciót ad például a metódusok deklarációjának finomhangolásához. Több olyan konstrukciót implementáltunk C++ban, ami a nyelvben eredetileg nincs benne: Java-ban használt felüldefiniálhatatlan final metódusok [101], elrejthetetlen metódusok, amelyek megakadályozzák, hogy eltérő deklarációval (véletlenül) elrejtsünk egy metódust [98], Eiffel-ben létező metódus átnevezés konstrukció [102]. Az Eiffel-ben használt tagok szelektív hozzáférését is megvalósítottuk template metaprogramok segítségével [56]. Ezen konstrukciók sablonok segítésével működnek és használatuk segítségével programozói hibákat lehet elkerülni. A C nyelv szabvány könyvtárának printf függvénye úgy működik, hogy első paramétere egy formázó string ami meghatározza, hogy a további pa-

13 Alapok 13 ramétereket hogyan kell kiírni az kimenetre. A formázó string értékét a fordítóprogramok nem kezelik, így használata hibákat okozhat. Kidolgoztunk egy metastring könyvtárat, melyben a string-ek értéke fordítás idejű információ. Ezekkel a metastring-ekkel a megírtuk a printf olyan verzióját, amely képes típus ellenőrzéseket elvégezni, így képes fordítás közben kiszűrni a programozói hibákat [104]. Hasonló problémák jöhetnek elő a multicore programozást támogató C++ könyvtár, a FastFlow kapcsán is [2]. A különböző task-ok egy void* (típustalan) pointer segítségével adnak át tetszőleges adatot egymásnak [99]. Ezt a hibalehetőséget sablonok segítségével elimináltuk a könyvtárból, sőt hatékonyabbá is tettük az implementációt: a virtuális függvények alkalmazását fordítási idejű mechanizmusra cseréltük sablonokkal [100]. Részt vettem a C++-hoz tervezett concept konstrukció egy bővítésében is, hogy a private, public és protected módosítók használhatóak legyenek concept map-ekben is [103]. Más nyelvek gyakran másképpen kezelik a generikus elemeket [9]. Különböző modern nyelvekben használatos nyelvi konstrukciót összehasonlítottam [85]. II.2. Generatív és generikus programozás A máig rendkívül széleskörben használt objektum-orientált programozás hiányosságaira fény derült az ezredfordulóra. Kiderültek a gyengeségei, és újabb programozási technikák alakultak ki, amelyekkel ezeket a gyengeségeket próbálták legyőzni. Azok a technikák, amelyek valamilyen eszköz (tool) segítségével generálnak kódot a generatív (generative) módszerek. Sokféle generatív technika létezik: a már említett template metaprogramozás is egy ide tartozó módszer: a fordítóprogram sablonok példányosításán keresztül kódot generál és értékel ki. Az aspektus-orientált programozás a logikailag elkülönülő, de fizikailag egybetartozó kódokat tudja aspektusokba modularizálni, amit egy aspektus-szövő szoftver (weaver) sző össze [48]. Az objektum-orientált jellegzetes gyengeségére az ún. expression problem világít rá [116]. Tekintsük az alábbi nyelvtant [109]: Exp ::= Lit Add Lit ::= (nem-negatív egész) Add ::= Exp + Exp Tegyük fel, hogy megvalósítunk egy print() műveletet, amellyel az output-ra kiírhatjuk a kifejezést. A feladat objektum-orientált megoldásához két különböző megoldás adható. Az első az adatközpontú: minden műveletet

14 14 Alapok virtuális metódusként definiálunk egy közös bázisosztályban, és minden specifikus osztályban felüldefiniáljuk. Ez a tipikus objektum-orientált megoldás, megvan az a moduláris tulajdonsága, hogy új osztályokat vehetünk fel úgy, hogy a meglévő kódhoz nem kell hozzányúlnunk, pl. kivonáshoz: Exp ::=... Neg Neg ::= - Exp Ha viszont egy új műveletet szeretnénk bevezetni, pl. eval, ami kiértékeli a (rész)kifejezést, akkor minden egyes osztályt módosítanunk kell, hogy specifikusan implementálhassuk a műveletet. A visitor design pattern [29] segítségével a műveleteket lehet osztályként ábrázolni: ilyenkor könnyű újabb műveleteket bevezetni a rendszerbe, de bonyolult feladat új adatszerkezeteket felvenni. Az objektum-orientált paradigma nem támogatja, hogy párhuzamosan az adat- és művelet-centrikusan is kiterjesszük az implementációt. Egy könyvtár esetében viszont, ha új műveleteket (algoritmusokat) kell bevezetni a könyvtár implementációját kellene módosítani, ami nem mindig oldható meg. Az egyik legfontosabb generatív paradigma, a generikus programozás [87] erre a problémára ad választ: az adatszerkezetek és műveletek absztrakt megfogalmazásával a komponensek konfigurálhatóságát és együttműködését megszervezi, miközben elvonatkoztat az érdektelen részletektől [59]. Dolgozatom központi témája a generikus programozáshoz tartozó STL helyes használata, de ezenkívül foglalkoztam aspektus-orientált programok helyességével [81] és metaprogramok helyességével is [73]. II.3. A C++ Standard Template Library A C++ Standard Template Library (STL) egy generikus programozási paradigmán (generic programming paradigm) alapuló könyvtár, mely része a C++ szabvány könyvtárának. Az STL kihasználja a C++ sablonok lehetőségeit, így egy bővíthető, hatékony, mégis flexibilis rendszert alkot. Az STL (és a generikus programozás) központi elve az általánosítás [53]. Scott Meyers az STL-t a szabványkönyvtár legforradalmibb részének tartja [54]. Kiemeli, hogy a felépítése, a rugalmassága, bővíthetősége, a szabvány miatti hatékonysága teszi nagyon jól használhatóvá. Szerinte az STL nem szoftver, hanem konvenciók halmaza, és emiatt forradalmi. Dewhurst viszont azt a tulajdonságát emeli ki, hogy a tárolók szerkezetükkel és működésükkel kapcsolatos döntések már fordítási időben megszületnek [17]. Emiatt hatékony és kicsi kód készül, mely teljesítmény tekintetében pontosan alkalmazkodik az adott felhasználási módhoz. Bruce Eckel az STL-nek azt a jó

15 Alapok 15 tulajdonságát is kiemeli, hogy teljesen platformfüggetlen [23]. Karbantartásilag az STL egyik legnagyobb előnye a szabványos névhasználatban rejlik: az STL komponensei minden C++ programozó számára ugyanazt jelentik. Ez olyan szemantikai többlettel jár, amit semmilyen kézzel írt kód nem tud megadni. A fenti jó tulajdonságok elsősorban az STL egyedi szerkezetével magyarázhatóak. Az STL alapvető komponensei: konténerek (containers), algoritmusok (algorithms), iterátorok (iterators), funktorok (functors), átalakítók (adaptors), allokátorok (allocators). A konténerek (pl. vector, set, map, stb.) alapvető feladata az adatok memóriában történő elhelyezése, tárolása és a memória konzisztensen tartása. A konténerek csoportosíthatóak: szekvenciális és asszociatív konténerekre. (Meyers egy másik csoportosítást is használ az STL konténerek kapcsán: láncolt és egybefüggő-memória konténerekre [53].) Az STL-ben három szabványos szekvenciális konténer sablon található: list, vector, deque, valamint a string konténer, ami konkrétan karakterek tárolására optimalizált. Ezeknél a felhasználó definiálja, hogy az elemek hova kerüljenek a konténerben. A vector egy olyan konténer, amely garantáltan egybefüggő tárterületen tárolja az elemeket, így gyorsan elérhető tetszőleges eleme, de a törlés és beszúrás műveletek csak a konténer végén hatékonyak. A vector közvetlen elérésű iterátorokat biztosít, amelynek segítségével az STL összes algoritmusa használható. A list konténer egy kétirányú láncolt lista, amelybe tetszőleges helyre hatékonyan lehet beszúrni illetve tetszőleges helyről lehet hatékonyan törölni, de a konténer tetszőleges eleme csak lineáris időben érhető el. A list konténer bidirectional, azaz kétirányú iterátorokat garantál. A deque egy kettős végű sor, ahol a konténer két végén lehet hatékonyan megváltoztatni a konténer méretét. Szintén random access kategóriájú iterátorokat biztosít. Ugyan ezek a konténerek hasonló interface-szel rendelkeznek, nem célszerű őket egymással felcserélhetőnek feltételezni. A vector és a string két nagyon hasonló adatszerkezet. Az interface különbségein túl a legfontosabb szemantikai különbség a kettő között a másolásban rejlik: a vector copy konstruktora és értékadó operátora kötelezően a sablon paraméter értékadó operátorával másolja a konténer összes elemét, a string viszont használhat referenciaszámlálást. Az STL-ben négy szabványos asszociatív sablon található: set, multiset, map, multimap. Az asszociatív konténerek rendezetten tárolják a bennük lévő elemeket, de a mögöttes valódi adatszerkezetet nem definiálja a C++ szabványa. Jellemzően piros-fekete fákat használnak az STL implementációk. A map és a multimap kulcs-érték párokat tartalmaz, a set és a multiset csak kulcsokat. A set-ben, map-ben nem lehet több ekvivalens

16 16 Alapok kulcs, egyedieknek kell lenniük. Ezzel szemben a multiset és a multimap támogatja az ekvivalens kulcsok multiplicitását. Az iterátorok garantálják az algoritmusok és a konténerek függetlenségét. Egy egységes interface segítségével definiálják a memóriában elhelyezett elemek elérését. Ez az interface a pointer-aritmetikán alapul: mutatók (pointerek) segítségével tömbökön végig lehet iterálni. Az iterátorok a pointerek absztrakciójának tekinthetőek. A pointerek használhatóak iterátorként is, a tömbökön az STL algoritmusai meghívhatóak. A pointer-aritmetika alapvető műveletei: prefix és postfix operator++: a következő elemre lépteti a pointert. operator*: a pointer által mutatott elem lekérdezése operator==: a két pointer ugyanarra az elemre hivatkozik-e prefix és postfix operator--: a megelőző elemre lépteti a pointert, A pointerek segítségével a tömbben tetszőleges pozícióra lehet ugrani bárhonnan. Ez nem igaz az összes STL-ben definiált iterátorra. Az STL iterátorai különböző kategóriákba esnek a képességeik alapján [46]. A kategóriák egy hierarchiát alakítottak ki a különböző iterátorok között: Ezek a kategóriák nyelvi szemszögből nincsenek megkülönböztetve, a C++ sablonjai megszorítás nélküliek, a C++ nyelv jelenleg nem tartalmaz concepteket. Azok az iterátorok teljesítik az input iterátorok elvárásait, amelyekkel egyszer végig lehet menni egy intervallumon és a benne lévő elemeket el lehet egyszer érni olvasásra. Ilyen iterátorokat használ például a for each algoritmus. Azok az iterátorok teljesítik az output iterátorok elvárásait, amelyekkel az elemek szekvenciálisan elérhetőek és írhatóak. Ilyet vár például a copy

17 Alapok 17 harmadik paramétereként. Az ostream iterator<t> sablon példányai tipikus output kategóriájú iterátorok. Azok az iterátorok teljesítik a forward iterátorok elvárásait, amelyekkel szekvenciálisan végig lehet menni az intervallumon, és az iterátorok olvasni és írni is tudják az elemeket. Mivel az input iterátorokkal szemben a forward iterátorokról másolatok készülhetnek az algoritmusok törzsében, azaz többször is hivatkozhatnak már elért elemet, akár többször is bejárható egy intervallum. Mivel a max element algoritmus iterátort ad vissza az input intervallum legnagyobb értékére, forward kategóriájú iterátort vár. Ha csak az intervallum legnagyobb értéket adná vissza, akkor input iterátort várna. Azok a forward iterátorok teljesítik a kétirányú (bidirectional) iterátorok elvárásait, amelyek képesek nem csak a következő, hanem az előző elemet is elérni. Például a list konténer iterátorai bidirectional iterátorok. Azok az iterátorok teljesítik a közvetlen vagy véletlen elérésű (randomaccess) iterátorok elvárásait, amelyek bidirectional iterátorok és képesek gyorsan (konstans időben) egynél több elemmel is növelni vagy csökkenteni a relatív címzés megvalósításához. Ezenkívül támogatniuk kell iterátorok öszszehasonlítását operator<, operator>=, stb. műveletekel. Ilyen kategóriájú iterátort vár például a sort algoritmus és például a vector konténer iterátorai is random-access kategóriájúak. A konténerek belső típusként négy fajta iterátor típust garantálnak: iterator const iterator reverse iterator const reverse iterator A konténerek begin() és end() tagfüggvényeivel tudunk konténer iterátorokat létrehozni. A begin() létrehoz egy olyan iterátort, ami konténer első elemére mutat, az end() pedig egy olyat, ami a konténer extremális végére mutat. A reverse iterátorok létrehozásához a konténerek rbegin() és rend() tagfüggvényei használhatóak. A const iterator és a const reverse iterator nem engedi az iterátor objektumokon keresztül megváltoztatni a konténer hivatkozott értékét, azt csak olvasni tudja. A C++ konstans-biztonságának fontos összetevői ezek az iterátorok. A reverse iterátorok (reverse iterator és const reverse iterator) az iterátorokhoz képest fordított irányban haladnak, a konténer végétől indulnak és a konténer elejéig mennek. Kényelmesen használhatóak, amikor például egy elem utolsó előfordulását kell megkeresni a find algoritmussal.

18 18 Alapok A konténerek iterátorain kívül az STL még biztosít néhány iterátor sablont, amelyekkel a stream-eken (például file-okon, standard input-on vagy output-on) lehet iterálni: istream iterator<t> ostream iterator<t> istreambuf iterator<t> ostreambuf iterator<t> Az istream iterator<t> és az ostream iterator<t> iterátorokat formázott input/output-hoz tervezték, ezek a sablon paraméter típusának kiíró (operator<<) és beolvasó (operator>>) operátorát hívják meg. Ezzel szemben, az istreambuf iterator<t> és ostreambuf iterator<t> iterátorokat karakterenkénti input/output-hoz tervezték, kevésbé rugalmasak, de a karakteres input/output-ot gyorsabban dolgozzák fel [53]. Követve az eddigi analógiát, azt mondhatnánk, hogy a függvényeket algoritmusokká általánosították, melyek a használt iterátorok típusa alapján paraméterezhetőek [53]. Az algoritmusok konténer-független függvénysablonok gyakori feladatokra, mint például keresés (pl. find, find if), stb.), rendezés (pl. partial sort, sort), másolás (pl. copy, unique copy), számlálás (pl. count, count if). Az algoritmusok belül valamilyen ciklusra képződnek le, azaz algoritmusok olyan függvények absztrakciói, amelyekben ciklusok vannak [4]. Az STL-nek 60 szabványos algoritmusa van [92]. Az algoritmusok konténer-függetlenek, de nem igaz az, hogy az összes algoritmus az összes konténerrel együttműködik, például a sort algoritmus random-access iterátorokat vár, így ha csak kétirányú list iterátorokat adunk át, akkor fordítási hibát kapunk. Az STL egyik nem elhanyagolható tulajdonsága, hogy az egyes tagfüggvények és algoritmusok futási ideje az intervallum vagy konténer méretéhez viszonyítva aszimptotikusan rögzített, amit minden implementációnak be kell tartania. Így például garantált, hogy a count algoritmus lineáris futási idejű, a set<key>::count tagfüggvény pedig logaritmikus. Az STL egyik fontos komponense a funktor [5]. Funktorok segítségével felhasználói kódrészleteket lehet hatékonyan végrehajtani a könyvtáron belül: funktorok definiálhatnak rendezéseket, predikátumokat, vagy valamilyen műveletet, amit végre szeretnénk hajtani az elemeken. Technikailag a funktorok egyszerű osztályok, amelyek rendelkeznek egy operator()-ral. (A funktorok ügyét nagymértékben segíti, hogy a paraméterek száma, a többi operátorral szemben, nincs előre definiálva az operator()

19 Alapok 19 esetében.) Jellemzően két tipikus helyen haszálnak funktorokat az STL-ben: algoritmusok paramétereként és asszociatív konténerek rendezéséhez. Algoritmusok esetében a funktorokhoz bevezetnek egy extra sablon paramétert, és az algoritmus egy ilyen típusú objektumot vár. Belül az algoritmus kódjában hivatkozik a paraméter operator()-ra: ez lehet egy függvénypointer dereferálása vagy a funktor operator()-a. Mivel ekkor a fordítóprogram paraméterdedukcióval levezeti a funktor típusát, képes inline-osítani a felhasználói kódrészletet. A függvénypointer esetében nem optimalizálhat a fordítóprogram, mert futás idejű információként kezeli azt, hogy a pointer hova (melyik függvényre) mutat. A funktorok osztályok, így lehetnek adattagjai, amelyek a külön hivatkozások között információ áramlást biztosíthatnak, és lehetnek konstruktorai, amelyeken keresztül extra paraméterek adhatóak át. Az aszszociatív konténerek esetében, magának a konténernek van egy extra sablon paramétere, ami a rendezés funktor típusát definiálja. Az alábbi példa bemutatja a for each algoritmus implementációját, amely gyakran használ funktort: template <class InputIterator, class UnaryFunction> UnaryFunction for_each( InputIterator first, InputIterator last, UnaryFunction f ) while( first!= last ) f( *first++ ); return f; A funktorokat lehet osztályozni, megkülönböztetünk unáris és bináris funktorokat. Az unáris funktoroknak operator()-ának egy, a bináris funktoroknak operator()-ának két paramétere van. Emellett megkülönböztetjük a predikátumokat, ezek olyan funktorok, amelyek operator()-a visszatérési érték típusa bool vagy konvertálódik bool-lá. Adaptálható (alkalmazkodóképes) funktorok a funktorok azon részcsoportja, amelyre a funktor adaptorok alkalmazhatóak. Kétféle szabványos funktor adaptor található az STL-ben: binder-ek és negálók [45]. A binderek (bind1st és bind2nd) egy bináris funktorból unárisat készítenek a funktor egyik paraméterének rögzítésével. A negáló adaptor-ok (not1 és not2) egy bináris vagy unáris predikátumot negálnak. Ahhoz, hogy egy funktor adaptálható legyen biztosítania kell néhány typedef-et, ami alapján

20 20 Alapok az adaptor definiálja annak az adaptált funktor operator()-ának viszszatérési érték és paraméter(ek) típusát. A következő typedef-ekre van szükség egy unáris funktor adaptálásához: argument type, result type. Egy bináris funktor adaptálásához szükség van a first argument type, a second argument type és result type szinonímákra. Ezeket a legegyszerűbben úgy lehet beállítani, ha a funktorunk a megfelelően példányosított unary function vagy binary function sablonból származik [17]. Példaképpen nézzük meg a következő kódrészletet: struct IsEven: std::unary_function<int, bool> bool operator()( const int& i ) const return 0 == i % 2; ; //... std::vector<int> v; //... std::vector<int>::iterator i = std::find_if( v.begin(), v.end(), std::not1( IsEven() ) ); Az IsEven egy adaptálható funktor típus, amely eldönti egy int értékről, hogy páros-e. A std::not1 az unáris funktort negálja, így a find if az első páratlan számot keresi a vector-ban. A szabványos könyvtárban már előre adott néhány funktor sablon, pl. a relációs műveleteken alapuló bináris funktorok: less, greater, stb., illetve néhány aritmetikai bináris műveleten alapuló sablon: például összeadás funktor sablonja a plus, a szorzásé a multiplies, stb.. Az STL átalakítói nem önálló komponensei a könyvtárnak, valamely komponenst alakítanak át egy eltérő funkcionalitás érdekében: léteznek konténer adaptorok, (tag)függvény adaptorok, funktor adaptorok, iterátor adaptorok. Az STL-ben három konténer adaptor létezik: queue, priority queue és stack. Ezek valamely paraméterezhető szekvenciális konténert alakítják át oly módon, hogy szűkített lehetőséggel bírjon specifikus adatszerkezetként. Az algoritmusok, amikor felhasználói kódrészletet hívnak egy globális függvényt hívnak meg: ez vagy egy globális függvényre mutató pointer vagy

21 Alapok 21 egy funktor típus operator()-a, de semmiképpen nem egy objektum tagfüggvényének a meghívása és nem egy pointeren keresztüli tagfüggvény meghívása. Ez utóbbi esetekben van szükségünk a tagfüggvény átalakítókra: mem fun és mem fun ref. Mindkettő kap egy tagfüggvény pointert, amiből a szükséges paramétereket levezeti és létrehoz egy olyan funktort, amelyben egy megfelelő típusú tagfüggvény pointer szerepel adattagként. Ennek az implementációs funktornak az operator()-a delegálja a hívást a tagfüggvény pointerhez. A mem fun ref felelős az objektumokon keresztüli tagfüggvény hívásért, a mem fun a pointereken keresztüli tagfüggvény hívásért. A ptr fun viselkedése is hasonló: egy globális függvényből készít o- lyan funktort, amely egy függvénypointeren keresztül hívja meg a felhasználói kódrészletet. A függvénnyel szemben a funktor alkalmazkodóképes, azaz alkalmazhatjuk a negálókat és binder-öket. Tehát, ha adott például egy predikátumfüggvényünk és negálni szeretnénk, akkor előtte ptr fun-nal funktorrá kell alakítanunk. A funktor adaptorokat a funktoroknál már bemutattam: két predikátum negáló (not1 és not2) és két binder (bind1st és bind2nd) funktor adaptor található a szabványos STL-ben. Az STL iterátor adaptorainak az a céljuk, hogy iterátort szimuláljanak specifikus céllal: konténerhez adjanak új elemeket. A konténerek iterátorai nem érik el azt a konténer objektumot, amelynek elemeire hivatkoznak, nem tudják meghívni a tagfüggvényeit, így nem tudnak elemeket hozzáadni az adatszerkezethez: csak meglévő elemeket érik el írási vagy olvasási céllal. Ez másolási algoritmusoknál problémás lehet, ha több elemet másolunk, mint amennyi átírható elem szerepel az output-ban. Az STL iterátor adaptorai megkapják a konténert (típussal együtt), így meghívhatóak azok a metódusai, amelyekkel új elemek vehetőek hozzá. A különféle beszúrásokhoz különböző adaptorok használhatóak: a back insert iterator a konténerek push back metódusát hívja meg, a front insert iterator pedig a push front metódusát. Mivel például az asszociatív konténereknek ilyen tagfüggvényei nincsenek, ekkor a insert iterator képes az insert tagfüggvény hívását kikényszeríteni az algoritmuson keresztül. A későbbiekben használni fogjuk az iterator traits sablont. Anélkül írunk le bizonyos iterátorhoz kapcsolódó típusokat, hogy magát az iterátorok kódját megváltoztatnánk, ezért ez egy nem-intrúzív technika. Ennek a sablonnak a specializációi különféle typedef-eket tartalmaznak, amelyekre szükség lehet az algoritmusok implementálásakor, például, hogy milyen típusú objektumokra hivatkoznak (value type). Az általános implementációja (ezt lehet specializálni) a következőképpen néz ki:

22 22 Alapok template <class T> struct iterator_traits typedef typename T::iterator_category iterator_category; typedef typename T::value_type value_type; typedef typename T::difference_type difference_type; typedef typename T::pointer pointer; typedef typename T::reference reference; ; A specializációk létrehozásához az iterator sablon bázisosztályt kell példányosítani. Az iterator traits sablon segítségével az algoritmusok túlterhelhetők az iterátor kategóriája alapján a tag dispatch-nek [96] nevezett technika segítségével. Ennek mintapéldája az advance algoritmus, amely a paraméterül kapott iterátort lépteti előre a paraméterül kapott értékkel. A túlterhelés miatt véletlen-elérésű iterátorok esetén a futás ideje konstans, egyébként lineáris. A túlterhelést úgy valósítják meg, hogy a szabványos deklarációra illeszkedő implementáció továbbhív eggyel több paraméterrel. Az extra paraméter egy default konstruált objektum, amelynek típusa az iterátor kategóriáját reprezentáló dummy típus. Ha ez std::random access iterator tag típusú, akkor közvetlen elérésű iterátort kapott az algoritmus és ezt kihasználhatja az implementáció: template <class InputIterator, class Distance> void advance( InputIterator& i, Distance n ) advance( i, n, typename std::iterator_traits<inputiterator>::iterator_category() ); template <class InputIterator, class Distance> void advance( InputIterator& i, Distance n, std::random_access_iterator_tag ) i += n; template <class InputIterator, class Distance> void advance( InputIterator& i,

23 Alapok 23 Distance n, std::bidirectional_iterator_tag ) for( Distance j = 0; j < n; ++j ) ++i; Az allokátorokat eredetileg a memóriamodellek absztrakciójaként fejlesztették ki, hogy ne kelljen megkülönböztetni a near és a far pointereket bizonyos 16-bites operációs rendszerekben. Arra is tervezték az allokátorokat, hogy elősegítse a memóriakezelők fejlesztését. A memóriaallokálás testreszabásához az összes szabványos STL konténer ad megoldást: az utolsó sablon paraméter az allokátor típusát definiálja. Van default értéke, de másik típus is megadható helyette. Az operator new-hoz és az operator new[]-hoz hasonlóan az STL allokátorok felelősek a nyers memória allokációjáért (és deallokációjáért), de az allokátorok kliensei kevés hasonlóságot hordoznak az operator new-hoz, az operator new[]-hoz vagy akár a malloc-hoz viszonyítva. Végül (de talán a legjelentősebb), hogy a szabványos konténerek nagyrésze sosem kér memóriát az allokátorától. Ennek az az oka, hogy láncolt adatszerkezetek (pl. list vagy az asszociatív adatszerkezetek nem a konténer value type typedef-je alapján kell memóriát allokálniuk, hanem egy belső implementációs struktúra elemeinek (pl. List node) [53]. Saját allokátorokat olyan helyzetben érdemes írni, ha a default allokátor szál-biztos (thread-safe) és nincs erre szükség, vagy speciális heap memóriát szeretnénk használni, ahol a konténer elemei egymáshoz közel helyezkednek el. Több folyamat által használt osztott memória használatakor is érdemes lehet saját allokátort írni. Az új C++ szabvány (C++11) magát az STL-t is bővítette. Ezek a bővítmények nem oldják meg a dolgozatban szereplő problémákat. A C++11 által biztosított STL új lehetőségeit később ismertetem az A függelékben. Az STL-t szekvenciális környezetre tervezték, ezért használata a szűk keresztmetszete lehet a multicore (többmagos) fejlesztéseknek. Részt vettem egy multicore környezetre optimalizált STL fejlesztésében is [105, 106, 107, 108]. Eközben végtelen intervallumok iterátorainak támogatását is megvalósítottuk [51].

24 24 Alapok II.4. Motivációs példák Ebben a fejezetben bemutatom azokat a nehézségeket, amelyekkel a programozóknak szembe kell nézniük az STL használatakor. Ismertetem azokat a problémákat, amelyeket az STL hibás használata okozhat. Ezek a hibák okozhatnak nehezen értelmezhető fordítási hibaüzeneteket, nem portábilis kódot, hibás futási eredményeket, memória szivárgást, korrupttá vagy inkonzisztenssé váló adatszerkezeteket illetve szükségtelen hatékonyságromlást. A most felsorolt problémák egy részére dolgozatom megoldást kínál, más problémák további kutatások tárgyai. II.4.1. Fordítási hibaüzenetek Az egyik leggyakoribb kritika ami az STL-t éri, az a fordítási hibaüzenetek érthetetlensége. A hosszú fordítási hibaüzenetek az STL implementációjára hivakoznak és nehéz kideríteni a probléma valódi okát. Ennek gyakori oka, hogy a C++ sablonok esetében nincs nyelvi eszköz a sablon paraméterekkel kapcsolatos elvárások leírására. Vegyük például az alábbi kódrészletet: std::list<int> a; std::sort( a.begin(), a.end() ); A kód látszólag rendben van, a sort (konténer-független) algoritmussal rendezni próbálunk egy lista adatszerkezetet. Mégis az alábbi hibaüzenetet kapjuk a fordítóprogramtól: /usr/include/c++/4.3/bits/stl_algo.h: In function void std::sort(_raiter, _RAIter) [with _RAIter = std::_list_iterator<int>] : listsort.cpp:7: instantiated from here /usr/include/c++/4.3/bits/stl_algo.h:4783: error: no match for operator- in last - first /usr/include/c++/4.3/bits/stl_algo.h: In function void std:: final_insertion_sort(_randomaccessiterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_list_iterator<int>] : /usr/include/c++/4.3/bits/stl_algo.h:4785: instantiated from void std::sort(_raiter, _RAIter) [with _RAIter = std::_list_iterator<int>] listsort.cpp:7: instantiated from here

25 Alapok 25 /usr/include/c++/4.3/bits/stl_algo.h:1827: error: no match for operator- in last - first /usr/include/c++/4.3/bits/stl_algo.h:1829: error: no match for operator+ in first + 16 /usr/include/c++/4.3/bits/stl_algo.h:1830: error: no match for operator+ in first + 16 /usr/include/c++/4.3/bits/stl_algo.h: In function void std:: insertion_sort(_randomaccessiterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_list_iterator<int>] : /usr/include/c++/4.3/bits/stl_algo.h:1833: instantiated from void std:: final_insertion_sort(_randomaccessiterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_list_iterator<int>] /usr/include/c++/4.3/bits/stl_algo.h:4785: instantiated from void std::sort(_raiter, _RAIter) [with _RAIter = std::_list_iterator<int>] listsort.cpp:7: instantiated from here /usr/include/c++/4.3/bits/stl_algo.h:1753: error: no match for operator+ in first + 1 /usr/include/c++/4.3/bits/stl_algo.h:1833: instantiated from void std:: final_insertion_sort(_randomaccessiterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_list_iterator<int>] /usr/include/c++/4.3/bits/stl_algo.h:4785: instantiated from void std::sort(_raiter, _RAIter) [with _RAIter = std::_list_iterator<int>] listsort.cpp:7: instantiated from here /usr/include/c++/4.3/bits/stl_algo.h:1759: error: no match for operator+ in i + 1 A hiba valódi oka az, hogy a sort algoritmus random-access kategóriájú iterátorokat vár, de a list konténernek csak bidirectional iterátorai vannak. A sort implementációjában azok a műveletek, amelyek kihasználják a közvetlen elérést fordítási hibákat okoznak, hiszen ilyen műveleteket a list bejárói nem támogatnak. Sajnos a hibaüzenet nem fejezi ki elég világosan, hogy a sort algoritmus nem használható a list konténerrel. Az ilyen jellegű problémákra olyan metaprogram könyvtárak adnak megoldást, amelyek fordítási időben már korábban ellenőrzik, hogy a sablon paraméter megfelele az elvárásoknak [118]. Ezek a könyvtárak azonban közel sem teljesek és implementáció-függőek. A kutatók a mai napig dolgoznak a concept-eken,

26 26 Alapok melyek nyelvi szintű konstrukcióként támogatják a sablonok típus paramétereinek ellenőrzését [103]. Ugyanennek a jelenségnek egy másik oka is van: a fordítóprogramok a hibaüzenetekben nem mindig arra az azonosítóra (vagy nem ugyanabban a formátumban) hivatkoznak, mint ami a forráskódban szerepel. A string-ek kezeléséhez az std::string típus használják a programozók. Maga az std::string nem önálló típus, hanem egy typedef. Az std::string egy szinonímája a std::basic string<char, char traits<char>, allocator<char> > típusnak. A hibaüzenetekben viszont ez utóbbi típusra hivatkozik a fordítóprogram, akkor is, ha a programozó az std::string-ként használja. A fenti hibaüzenetben ilyen a List iterator<int> implementáció-specifikus azonosító is, ami az std::list<int>::iterator szabványos típus álneve. Az asszociatív konténerek alatt lévő adatszerkezetet nem definiálja a C++ szabványa. A leggyakrabban piros-fekete fák [12] segítségével implementálják az asszociatív adatszerkezeteket. Egy implementációtól függő segéd sablon típusban (pl. Rb tree vagy Tree) megvalósítják az adatszerkezetet, a szabványos konténerek pedig ezeket a segédtípusokat használják. Vegyük most az alábbi hibás kódrészletet: std::set<std::string> a; a.insert( a ); A g++ fordítóprogram az alábbi hibaüzenetet adja az előző kódrészletre: seterr.cpp:11: error: no matching function for call to std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::insert( std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >&) /usr/include/c++/4.3/bits/stl_set.h:378: note: candidates are: std::pair<typename std::_rb_tree<_key, _Key, std::_identity<_key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_key, _Compare, _Alloc>::insert(const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Compare = std::less<std::basic_string<char,

27 Alapok 27 std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >] /usr/include/c++/4.3/bits/stl_set.h:405: note: typename std::_rb_tree<_key, _Key, std::_identity<_key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator std::set<_key, _Compare, _Alloc>::insert(typename std::_rb_tree<_key, _Key, std::_identity<_key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, const _Key&) [with _Key = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Compare = std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >] Látható, hogy a hibaüzenetben olyan típusok is megjelennek nagy menynyiségben, melyek a forráskódban sehol sem láthatóak: például konténer default sablonparaméterei és egyéb implementációs segédtípusok. Világos, hogy ezek a hibaüzenetek megértése nagy gyakorlatot kíván. Létezik platform specifikus eszköz a hibaüzenetek megértéséhez [117], de nincsen általánosan használható kényelmes eszköz erre a problémára. II.4.2. Invalid iterátorok Az iterátorok központi elemei az STL-nek: összekötik az algoritmusokat a konténerekkel, és a konténerek bejárását biztosítják. Sajnos azonban az iterátor objektumok élettartama nem feltétlenül esik egybe a hivatkozott objektum élettartalmával. Előfordulhat, hogy egy iterátor olyan objektumra hivatkozik, ami már nincs a memóriában vagy máshova került. A vector konténer sablon tipikus implementációja olyan, hogy lefoglal egy egybefüggő tárterületet valamekkora kapacitással. Ha betelik ez a kapacitás, akkor lefoglal egy nagyobb (jellemzően kétszer akkora) egybefüggő tárterületet, az elemeket átmásolja a régi tárterületről az újra, és a régi tárterületet felszabadítja a konténer. Nem garantált, hogy ezt a konténerhez tartozó iterátorok észreveszik. Több STL implementációnál az iterátorok továbbra is régi tárterületre hivatkoznak, és ha hivatkozunk ezekre az iterátorokra, akkor az nemdefiniált eredményhez vezet. Vegyük például az alábbi kódrészletet: std::vector<int> v; int x; //...

C++ Standard Template Library (STL)

C++ Standard Template Library (STL) Programozási Nyelvek és Fordítóprogramok Tanszék Programozási Nyelvek I. Témák 1 STL alapok 2 STL fogalmak 3 Konténerek 4 Iterátorok 5 Funktorok C++ STL Ne fedezzük fel újra spanyolviaszt! Sok adatszerkezet/algoritmus

Részletesebben

Fejlett programozási nyelvek C++ Iterátorok

Fejlett programozási nyelvek C++ Iterátorok Fejlett programozási nyelvek C++ Iterátorok 10. előadás Antal Margit 2009 slide 1 Témakörök I. Bevezetés II. Iterátor definíció III. Iterátorok jellemzői IV. Iterátorkategóriák V. Iterátor adapterek slide

Részletesebben

Challenge Accepted:C++ Standard Template Library

Challenge Accepted:C++ Standard Template Library Challenge Accepted: C++ Standard Template Library ELTE Informatikai Kar, Programozási Nyelvek és Fordítóprogramok Tanszék patakino@elte.hu Szakmai Esti Mesék C++ Standard Template Library Felépítése konténerek:

Részletesebben

Generatív programok helyessége

Generatív programok helyessége Generatív programok helyessége Doktori értekezés tézisei 2013 Pataki Norbert patakino@elte.hu Témavezető: Dr. Porkoláb Zoltán, egyetemi docens Eötvös Loránd Tudományegyetem, Informatikai Kar, 1117 Budapest,

Részletesebben

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon 1. Template (sablon) 1.1. Függvénysablon Maximum függvény megvalósítása függvénynév túlterheléssel. i n l i n e f l o a t Max ( f l o a t a, f l o a t b ) { return a>b? a : b ; i n l i n e double Max (

Részletesebben

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben?

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben? 1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben? 3. Ismertesse a névtér fogalmát! 4. Mit értünk a "változó hatóköre"

Részletesebben

Az alábbi példában a Foo f(5); konstruktor hívása után mennyi lesz f.b értéke? struct Foo { int a, b; Foo(int c):a(c*2),b(c*3) {} };

Az alábbi példában a Foo f(5); konstruktor hívása után mennyi lesz f.b értéke? struct Foo { int a, b; Foo(int c):a(c*2),b(c*3) {} }; A C++ kódokban lévő makrókat melyik egység dolgozza fel az alábbiak közül? preprocessor A szabványos C++-ban nem is írhatunk makrókat (csak C-ben) assembler linker Az alábbi példában a Foo f(5); konstruktor

Részletesebben

1) Hány byte-on tárol a C++ egy karaktert (char)? implementáció-függő ( viszont lásd 79. megjegyzés ) 1 8 4

1) Hány byte-on tárol a C++ egy karaktert (char)? implementáció-függő ( viszont lásd 79. megjegyzés ) 1 8 4 1) Hány byte-on tárol a C++ egy karaktert (char)? implementáció-függő ( viszont lásd 79. megjegyzés ) 1 8 4 2) Hány byte-on tárol a C++ egy float-ot? implementáció-függő 6 4 8 3) Hány byte-on tárol a C++

Részletesebben

Generikus Típusok, Kollekciók

Generikus Típusok, Kollekciók Generikus Típusok, Kollekciók Tóth Zsolt Miskolci Egyetem 2013 Tóth Zsolt (Miskolci Egyetem) Generikus Típusok, Kollekciók 2013 1 / 26 Tartalomjegyzék 1 Enumeráció 2 Generikus Típusok 3 Kollekciók System.Collections

Részletesebben

Már megismert fogalmak áttekintése

Már megismert fogalmak áttekintése Interfészek szenasi.sandor@nik.bmf.hu PPT 2007/2008 tavasz http://nik.bmf.hu/ppt 1 Témakörök Polimorfizmus áttekintése Interfészek Interfészek kiterjesztése Eseménykezelési módszerek 2 Már megismert fogalmak

Részletesebben

OOP #14 (referencia-elv)

OOP #14 (referencia-elv) OOP #14 (referencia-elv) v1.0 2003.03.19. 21:22:00 Eszterházy Károly Főiskola Információtechnológia tsz. Hernyák Zoltán adj. e-mail: aroan@ektf.hu web: http://aries.ektf.hu/~aroan OOP OOP_14-1 - E jegyzet

Részletesebben

GENERIKUS PROGRAMOZÁS Osztálysablonok, Általános felépítésű függvények, Függvénynevek túlterhelése és. Függvénysablonok

GENERIKUS PROGRAMOZÁS Osztálysablonok, Általános felépítésű függvények, Függvénynevek túlterhelése és. Függvénysablonok GENERIKUS PROGRAMOZÁS Osztálysablonok, Általános felépítésű függvények, Függvénynevek túlterhelése és Függvénysablonok Gyakorlatorientált szoftverfejlesztés C++ nyelven Visual Studio Community fejlesztőkörnyezetben

Részletesebben

Alprogramok, paraméterátadás

Alprogramok, paraméterátadás ELTE Informatikai Kar, Programozási Nyelvek és Fordítóprogramok Tanszék October 24, 2016 Programozási nyelvek Alprogramok Függvények, eljárások Metódusok Korutinok stb. Alprogramok Alprogram: olyan nyelvi

Részletesebben

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók

STL. Algoritmus. Iterátor. Tároló. Elsődleges komponensek: Tárolók Algoritmusok Bejárók STL Elsődleges komponensek: Tárolók Algoritmusok Bejárók Másodlagos komponensek: Függvény objektumok Adapterek Allokátorok (helyfoglalók) Tulajdonságok Tárolók: Vektor (vector) Lista (list) Halmaz (set)

Részletesebben

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1

STL gyakorlat C++ Izsó Tamás május 9. Izsó Tamás STL gyakorlat/ 1 STL gyakorlat C++ Izsó Tamás 2016. május 9. Izsó Tamás STL gyakorlat/ 1 Komponensek kapcsolata Deklarálja az alábbi osztálydiagramon szereplő osztályok közül az A, AA és AB osztályokat! A konstruktorokat

Részletesebben

Programozási technológia

Programozási technológia Programozási technológia Generikus osztályok Gyűjtemények Dr. Szendrei Rudolf ELTE Informatikai Kar 2018. Generikus osztályok Javaban az UML paraméteres osztályainak a generikus (sablon) osztályok felelnek

Részletesebben

Programozási nyelvek Java

Programozási nyelvek Java Programozási nyelvek Java 11.gyakorlat Operációsrendszertől függő tulajdonságok PATH elválasztó Unix ":" Windows ";" final String PATH_SEPARATOR = File.pathSeparator; Ugyanaz, csak karakterkent final char

Részletesebben

1.AA MEGOLDÓ BERCI AA 1.

1.AA MEGOLDÓ BERCI AA 1. Programozás alapjai 2. (inf.) 2. zárthelyi 2015.05.07. gyak./lab. hiányzás: 3/2 Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot, de csak a feladatlapra írt megoldásokat

Részletesebben

Interfészek. PPT 2007/2008 tavasz.

Interfészek. PPT 2007/2008 tavasz. Interfészek szenasi.sandor@nik.bmf.hu PPT 2007/2008 tavasz http://nik.bmf.hu/ppt 1 Témakörök Polimorfizmus áttekintése Interfészek Interfészek kiterjesztése 2 Már megismert fogalmak áttekintése Objektumorientált

Részletesebben

500. AA Megoldó Alfréd AA 500.

500. AA Megoldó Alfréd AA 500. Programozás alapjai 2. NZH 2010.05.13. gyakorlat: / Hiány:0 ZH:0 MEGOLD IB.027/51. Hftest: 0 Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti, hogy minden

Részletesebben

Bevezetés a programozásba 2

Bevezetés a programozásba 2 Bevezetés a programozásba 2 7. Előadás: STL konténerek, sablonok http://digitus.itk.ppke.hu/~flugi/ Vector int int main() { vector v(10); int int sum=0; for for (int i=0;i

Részletesebben

GTL Graphical Template Library

GTL Graphical Template Library Eötvös Loránd Tudományegyetem Informatikai Kar Programozási Nyelvek és Fordítóprogramok Tanszék GTL Graphical Template Library Vatai Emil V. éves Programtervező Matematikus hallgató Témavezető: Dr. Porkoláb

Részletesebben

C++ programozási nyelv

C++ programozási nyelv C++ programozási nyelv Gyakorlat - 13. hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2004. december A C++ programozási nyelv Soós Sándor 1/10 Tartalomjegyzék Objektumok

Részletesebben

Programozási Nyelvek: C++

Programozási Nyelvek: C++ Programozási Nyelvek: C++ Gyakorló feladatkönyv Umann Kristóf #include "CppStudent.h" int main() { CppStudent *reader = new CppStudent(); reader->readbook(); while(!reader->doesunderstand()) { reader->exercise();

Részletesebben

Generikus osztályok, gyűjtemények és algoritmusok

Generikus osztályok, gyűjtemények és algoritmusok Programozási, gyűjtemények és algoritmusok bejárása Informatikai Kar Eötvös Loránd Tudományegyetem 1 Tartalom 1 bejárása 2 bejárása 2 Java-ban és UML-ben bejárása Az UML-beli paraméteres osztályok a Java

Részletesebben

1. Bevezetés A C++ nem objektumorientált újdonságai 3

1. Bevezetés A C++ nem objektumorientált újdonságai 3 Előszó xiii 1. Bevezetés 1 2. A C++ nem objektumorientált újdonságai 3 2.1. A C és a C++ nyelv 3 2.1.1. Függvényparaméterek és visszatérési érték 3 2.1.2. A main függvény 4 2.1.3. A bool típus 4 2.1.4.

Részletesebben

ISA szimulátor objektum-orientált modell (C++)

ISA szimulátor objektum-orientált modell (C++) Budapesti Műszaki és Gazdaságtudományi Egyetem ISA szimulátor objektum-orientált modell (C++) Horváth Péter Elektronikus Eszközök Tanszéke 2015. február 12. Horváth Péter ISA szimulátor objektum-orientált

Részletesebben

OpenCL alapú eszközök verifikációja és validációja a gyakorlatban

OpenCL alapú eszközök verifikációja és validációja a gyakorlatban OpenCL alapú eszközök verifikációja és validációja a gyakorlatban Fekete Tamás 2015. December 3. Szoftver verifikáció és validáció tantárgy Áttekintés Miért és mennyire fontos a megfelelő validáció és

Részletesebben

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

Bánsághi Anna 2014 Bánsághi Anna 1 of 33 IMPERATÍV PROGRAMOZÁS Bánsághi Anna anna.bansaghi@mamikon.net 7. ELŐADÁS - ABSZTRAKT ADATTÍPUS 2014 Bánsághi Anna 1 of 33 TEMATIKA I. ALAPFOGALMAK, TUDOMÁNYTÖRTÉNET II. IMPERATÍV PROGRAMOZÁS Imperatív

Részletesebben

C++ referencia. Izsó Tamás február 17. A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák:

C++ referencia. Izsó Tamás február 17. A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák: C++ referencia Izsó Tamás 2017. február 17. 1. Bevezetés A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák: Sokan összetévesztik a pointerrel. Keveset alkalmazzák

Részletesebben

OOP. Alapelvek Elek Tibor

OOP. Alapelvek Elek Tibor OOP Alapelvek Elek Tibor OOP szemlélet Az OOP szemlélete szerint: a valóságot objektumok halmazaként tekintjük. Ezen objektumok egymással kapcsolatban vannak és együttműködnek. Program készítés: Absztrakciós

Részletesebben

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*;

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*; Java osztály készítése, adattagok, és metódusok, láthatóság, konstruktor, destruktor. Objektum létrehozása, használata, öröklés. ( Előfeltétel 12. Tétel ) Az osztály egy olyan típus leíró struktúra, amely

Részletesebben

mul : S T N 1 ha t S mul(s, t) := 0 egyébként Keresés Ezt az eljárást a publikus m veletek lenti megvalósításánál használjuk.

mul : S T N 1 ha t S mul(s, t) := 0 egyébként Keresés Ezt az eljárást a publikus m veletek lenti megvalósításánál használjuk. Érdi Gerg EF II. 2/2. Feladat Készítsen egy zsák típust! lkalmazzon osztályt! zsákokat rendezett láncolt listával ábrázolja! Implementálja a szokásos m veleteket, egészítse ki az osztályt a kényelmes és

Részletesebben

Programozás módszertan

Programozás módszertan Programozás módszertan p. Programozás módszertan Operátorok túlterhelése a C++ nyelvben Pere László (pipas@linux.pte.hu) PÉCSI TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR INFORMATIKA TANSZÉK Bevezetés Programozás

Részletesebben

C++ programozási nyelv Konstruktorok-destruktorok

C++ programozási nyelv Konstruktorok-destruktorok C++ programozási nyelv Konstruktorok-destruktorok Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2004. szeptember A C++ programozási nyelv Soós Sándor 1/20 Tartalomjegyzék

Részletesebben

Bevezetés a C++ programozási nyelvbe

Bevezetés a C++ programozási nyelvbe Bevezetés a C++ programozási nyelvbe Miskolci Egyetem Általános Informatikai Tanszék CPP0 / 1 Története A C++ programozási nyelv a C programozási nyelv objektum orientált kiterjesztése. Az ANSI-C nyelvet

Részletesebben

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék Speciális adattagok és tagfüek Miskolci Egyetem Általános Informatikai Tanszék CPP7 / 1 Statikus adattagok Bármely adattag lehet static tárolási osztályú A statikus adattag az osztály valamennyi objektuma

Részletesebben

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism)

Programozás alapjai C nyelv 8. gyakorlat. Mutatók és címek (ism.) Indirekció (ism) Programozás alapjai C nyelv 8. gyakorlat Szeberényi Imre BME IIT Programozás alapjai I. (C nyelv, gyakorlat) BME-IIT Sz.I. 2005.11.07. -1- Mutatók és címek (ism.) Minden változó és függvény

Részletesebben

C vagy C++? Programozási Nyelvek és Fordítóprogramok Tanszék. Pataki Norbert. Programozási Nyelvek I.

C vagy C++? Programozási Nyelvek és Fordítóprogramok Tanszék. Pataki Norbert. Programozási Nyelvek I. Programozási Nyelvek és Fordítóprogramok Tanszék Programozási Nyelvek I. Témák 1 Bevezetés 2 A C++ alapfilozófiája 3 Névterek/namespace-ek 4 Függvények 5 Referenciák C++-ban Motiváció A C és a C++ nyelv

Részletesebben

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum Bevezetés a programozásba 2 1. Előadás: Tagfüggvények, osztály, objektum Ismétlés int main() { string s; s; s= bla ; cout

Részletesebben

Osztályok. 4. gyakorlat

Osztályok. 4. gyakorlat Osztályok 4. gyakorlat Az osztály fogalma Az objektumok formai leírása, melyek azonos tulajdonsággal és operációkkal rendelkeznek. Osztályból objektum készítését példányosításnak nevezzük. Minden objektum

Részletesebben

1000.AA Megoldo Alfréd 1000.A

1000.AA Megoldo Alfréd 1000.A Programozás alapjai 2. (inf.) 2. PZH 2018.05.22. hiányzás:0+3 L4-R4P ZH: 27,5+26 ABCDEF IB.028/100. Sum:0 e:19 Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot, de

Részletesebben

Smart Pointer koncepciója

Smart Pointer koncepciója Smart Pointer koncepciója ( Egyszerű Smart Pointer implementálása C++ nyelven ) Bevezetés Mik a smart pointer-ek 1? A válasz egyszerű; a smart pointer-ek olyan mutatók amik okosak. Mit is jelent ez pontosan?

Részletesebben

Programozási nyelvek (ADA)

Programozási nyelvek (ADA) Programozási nyelvek (ADA) Kozsik Tamás előadása alapján Készítette: Nagy Krisztián 1. előadás Hasznos weboldal http://kto.web.elte.hu Program felépítése Programegységek (program unit) eljárások (procedure)

Részletesebben

Programozási alapismeretek 4.

Programozási alapismeretek 4. Programozási alapismeretek 4. Obejktum-Orientált Programozás Kis Balázs Bevezetés I. Az OO programozási szemlélet, egy merőben más szemlélet, az összes előző szemlélettel (strukturális, moduláris, stb.)

Részletesebben

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek

Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek Algoritmusok és adatszerkezetek gyakorlat 06 Adatszerkezetek Tömb Ugyanolyan típusú elemeket tárol A mérete előre definiált kell legyen és nem lehet megváltoztatni futás során Legyen n a tömb mérete. Ekkor:

Részletesebben

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában

Mutatók és címek (ism.) Programozás alapjai C nyelv 8. gyakorlat. Indirekció (ism) Néhány dolog érthetőbb (ism.) Változók a memóriában Programozás alapjai C nyelv 8. gyakorlat Szeberényi mre BME T Programozás alapjai. (C nyelv, gyakorlat) BME-T Sz.. 2005.11.07. -1- Mutatók és címek (ism.) Minden változó és függvény

Részletesebben

3. Osztályok II. Programozás II

3. Osztályok II. Programozás II 3. Osztályok II. Programozás II Bevezető feladat Írj egy Nevsor osztályt, amely legfeljebb adott mennyiségű nevet képes eltárolni. A maximálisan tárolható nevek számát a konstruktorban adjuk meg. Az osztályt

Részletesebben

Objektumelvű programozás

Objektumelvű programozás Objektum, osztály Objektumelvű programozás Az elemzés együttműködő objektumok rendszereként fogalmazza meg a feladatot. Objektum-központú elemzés A tervezés a feladat tárgyköreit egy-egy objektum felelősségévé

Részletesebben

Bevezetés, a C++ osztályok. Pere László

Bevezetés, a C++ osztályok. Pere László Programozás módszertan II. p. Programozás módszertan II. Bevezetés, a C++ osztályok Pere László (pipas@linux.pte.hu) PÉCSI TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR INFORMATIKA ÉS ÁLTALÁNOS TECHNIKA TANSZÉK

Részletesebben

500.AA Megoldó Kulcsár 500.A

500.AA Megoldó Kulcsár 500.A Programozás alapjai 2. (inf.) 2. ZH 2019.05.14. lab. hiányzás: + / HFt: ABC123 IL.305./1. p: e: Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot, de csak a feladatlapra

Részletesebben

Objektum orientált kiterjesztés A+ programozási nyelvhez

Objektum orientált kiterjesztés A+ programozási nyelvhez Szegedi Tudományegyetem Informatikai Tanszékcsoport Objektum orientált kiterjesztés A+ programozási nyelvhez Diplomamunka terve Készítette: Bátori Csaba programtervező matematikus hallgató Témavezető:

Részletesebben

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok A szemantikus elemzés helye Forrásprogram Forrás-kezelő (source handler) Lexikális elemző (scanner) A szemantikus elemzés feladatai Fordítóprogramok előadás (A, C, T szakirány) Szintaktikus elemző (parser)

Részletesebben

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok

Bevezetés a programozásba II. 5. Előadás: Másoló konstruktor, túlterhelés, operátorok Bevezetés a programozásba II 5. Előadás: Másoló konstruktor, túlterhelés, operátorok Emlékeztető struct Vektor { int meret, *mut; Vektor(int meret); int szamlal(int mit); }; int Vektor::szamlal(int mit)

Részletesebben

2011.11.29. JUnit. JUnit használata. IDE támogatás. Parancssori használat. Teszt készítése. Teszt készítése

2011.11.29. JUnit. JUnit használata. IDE támogatás. Parancssori használat. Teszt készítése. Teszt készítése Tartalom Integrált fejlesztés Java platformon JUnit JUnit használata Tesztelési technikák Demo 2 A specifikáció alapján teszteljük a program egyes részeit, klasszikus V-modell szerint Minden olyan metódust,

Részletesebben

C++ programozási nyelv

C++ programozási nyelv C++ programozási nyelv Gyakorlat - 8. hét Nyugat-Magyarországi Egyetem Faipari Mérnöki Kar Informatikai Intézet Soós Sándor 2004. november A C++ programozási nyelv Soós Sándor 1/12 Tartalomjegyzék Miért

Részletesebben

C++11 TÓTH BERTALAN C++ PROGRAMOZÁS STL KONTÉNEREKKEL

C++11 TÓTH BERTALAN C++ PROGRAMOZÁS STL KONTÉNEREKKEL C++11 TÓTH BERTALAN C++ PROGRAMOZÁS STL KONTÉNEREKKEL Tóth Bertalan: C++ programozás STL konténerekkel 2016 Jelen dokumentumra a Creative Commons Nevezd meg! Ne add el! Ne változtasd meg! 3.0 Unported

Részletesebben

500. CC Megoldó Alfréd CC 500.

500. CC Megoldó Alfréd CC 500. Programozás alapjai 2. PótZH 2010.05.20. gyakorlat: G1/IB.146 Hiány:3 ZH:7,71 MEGOLD SCH/500. Hftest: 0 ZHp: Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

Mutatók és mutató-aritmetika C-ben március 19.

Mutatók és mutató-aritmetika C-ben március 19. Mutatók és mutató-aritmetika C-ben 2018 március 19 Memória a Neumann-architektúrában Neumann-architektúra: a memória egységes a címzéshez a természetes számokat használjuk Ugyanabban a memóriában van:

Részletesebben

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error

List<String> l1 = new ArrayList<String>(); List<Object> l2 = l1; // error Generics Egyszerűbb példák (java.util csomagból): public interface List { void add(e x); Iterator iterator(); public interface Iterator { E next(); boolean hasnext(); E - formális típusparaméter,

Részletesebben

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban Tartalom OOP ismétlés Osztályok létrehozása Adattagok láthatóságai, elnevezési ajánlások Konstruktor, destruktor this pointer Statikus és dinamikus

Részletesebben

Collections. Összetett adatstruktúrák

Collections. Összetett adatstruktúrák Collections Összetett adatstruktúrák Collections framework Előregyártott interface-ek és osztályok a leggyakoribb összetett adatszerkezetek megvalósítására Legtöbbször módosítás nélkül használhatók Időt,

Részletesebben

Virtuális függvények (late binding)

Virtuális függvények (late binding) Virtuális függvények (late binding) Miskolci Egyetem Általános Informatikai Tanszék Virtuális függvények CPP5 / 1 Azonos nevű függvények megkülönböztetése paraméterszignatúra (függvény overloading) - egy

Részletesebben

Osztálytervezés és implementációs ajánlások

Osztálytervezés és implementációs ajánlások Osztálytervezés és implementációs ajánlások Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2006. 04. 24. Osztálytervezés és implementációs kérdések OTERV / 1 Osztály tervezés Egy nyelv

Részletesebben

Felhasználó által definiált adattípus

Felhasználó által definiált adattípus Felhasználó által definiált adattípus C++ Izsó Tamás 2017. február 24. Izsó Tamás Felhasználó által definiált adattípus/ 1 Irodalom Izsó Tamás Felhasználó által definiált adattípus/ 2 Programtervezési

Részletesebben

Osztálytervezés és implementációs ajánlások

Osztálytervezés és implementációs ajánlások Osztálytervezés és implementációs ajánlások Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2006. 04. 24. Osztálytervezés és implementációs kérdések OTERV / 1 Osztály tervezés Egy nyelv

Részletesebben

Számítógép és programozás 2

Számítógép és programozás 2 Számítógép és programozás 2 10. Előadás Öröklődés http://digitus.itk.ppke.hu/~flugi/ Tagfüggvény struct Particle { int x,y; unsigned char r,g,b; void rajzol() { gout

Részletesebben

Programozás II gyakorlat. 8. Operátor túlterhelés

Programozás II gyakorlat. 8. Operátor túlterhelés Programozás II gyakorlat 8. Operátor túlterhelés Kezdő feladat Írjunk egy Vector osztályt, amely n db double értéket tárol. A konstruktor kapja meg az elemek számát. Írj egy set(int idx, double v) függvényt,

Részletesebben

C++ Gyakorlat jegyzet 10. óra.

C++ Gyakorlat jegyzet 10. óra. C++ Gyakorlat jegyzet 10. óra. A jegyzetet Umann Kristóf készítette Brunner Tibor és Horváth Gábor gyakorlatán. (2017. január 6.) 1. Iterátor kategóriák Korábban már elhangzott, hogy az általunk implementált

Részletesebben

C++ Standard Template Library

C++ Standard Template Library Haladó C++, 1/ 78 C++ Standard Template Library Pataki Norbert 2014. április 2. Haladó C++, 2/ 78 Generic programming, generikus programozás Expression problem OOP vs. generic programming Párhuzamos bővíthetőség

Részletesebben

Objektumok inicializálása

Objektumok inicializálása Objektumok inicializálása Miskolci Egyetem Általános Informatikai Tanszék Objektumok inicializálása CPP4 / 1 Tartalom public adattagok inicializálása felsorolással konstruktor objektum tömbök osztály típusú

Részletesebben

és az instanceof operátor

és az instanceof operátor Java VIII. Az interfacei és az instanceof operátor Krizsán Zoltán Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2005. 10. 24. Java VIII.: Interface JAVA8 / 1 Az interfészről általában

Részletesebben

.AA Megoldó Alfréd AA.

.AA Megoldó Alfréd AA. Programozás alapjai 2. (inf.) pót zárthelyi 2013.05.23. gyak. hiányzás: kzh: ZH:0 ABCDEF MEG/200. Hftest: (p) Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán Java VIII. Az interfacei és az instanceof operátor Krizsán Zoltán Miskolci Egyetem Általános Informatikai Tanszék Utolsó módosítás: 2005. 10. 24. Java VIII.: Interface JAVA8 / 1 Az interfészről általában

Részletesebben

Globális operátor overloading

Globális operátor overloading Programozás II. 9. gyakorlat Operátor overloading 2: Unáris operátorok, globálisan megvalósított operátorok, > operátorok Kivételkezelés, IO library Globális operátor overloading Előző alkalommal

Részletesebben

A TANTÁRGY ADATLAPJA

A TANTÁRGY ADATLAPJA A TANTÁRGY ADATLAPJA 1. A képzési program adatai 1.1 Felsőoktatási intézmény Babeș-Bolyai Tudományegyetem 1.2 Kar Matematika és Informatika 1.3 Intézet Magyar Matematika és Informatika 1.4 Szakterület

Részletesebben

Eseménykezelés. Szoftvertervezés és -fejlesztés II. előadás. Szénási Sándor.

Eseménykezelés. Szoftvertervezés és -fejlesztés II. előadás.   Szénási Sándor. Eseménykezelés előadás http://nik.uni-obuda.hu/sztf2 Szénási Sándor szenasi.sandor@nik.uni-obuda.hu Óbudai Egyetem,Neumann János Informatikai Kar Függvénymutatókkal Származtatással Interfészekkel Egyéb

Részletesebben

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés Bevezetés a programozásba 2 7. Előadás: Objektumszű és osztályszű elemek, hibakezelés ISMÉTLÉS Osztály class Particle { public: Particle( X, X, Y); virtual void mozog( ); ); virtual void rajzol( ) const;

Részletesebben

C# osztálydeníció. Krizsán Zoltán 1. .net C# technológiák tananyag objektum orientált programozás tananyag

C# osztálydeníció. Krizsán Zoltán 1. .net C# technológiák tananyag objektum orientált programozás tananyag C# osztálydeníció Krizsán Zoltán 1 Általános Informatikai Tanszék Miskolci Egyetem.net C# technológiák tananyag objektum orientált programozás tananyag Tartalom 1 Bevezetés 2 Osztály létrehozása, deníció

Részletesebben

PROGRAMOZÁS tantárgy. Gregorics Tibor egyetemi docens ELTE Informatikai Kar

PROGRAMOZÁS tantárgy. Gregorics Tibor egyetemi docens ELTE Informatikai Kar PROGRAMOZÁS tantárgy Gregorics Tibor egyetemi docens ELTE Informatikai Kar Követelmények A,C,E szakirány B szakirány Előfeltétel Prog. alapismeret Prog. alapismeret Diszkrét matematika I. Óraszám 2 ea

Részletesebben

500.AA Megoldo Arisztid 500.A

500.AA Megoldo Arisztid 500.A Programozás alapjai 2. (inf.) 2. ZH 2018.05.07. lab. hiányzás: 1+2 a/a/1 ABCD123 a/1. kzh: 4 E:3 Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot, de csak a feladatlapra

Részletesebben

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

Programozás I. 3. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar Programozás I. 3. gyakorlat Szegedi Tudományegyetem Természettudományi és Informatikai Kar Antal Gábor 1 Primitív típusok Típus neve Érték Alap érték Foglalt tár Intervallum byte Előjeles egész 0 8 bit

Részletesebben

Programozás II. 4. Dr. Iványi Péter

Programozás II. 4. Dr. Iványi Péter Programozás II. 4. Dr. Iványi Péter 1 inline függvények Bizonyos függvények annyira rövidek, hogy nem biztos hogy a fordító függvényhívást fordít, hanem inkább az adott sorba beilleszti a kódot. #include

Részletesebben

0. Megoldó Manó 0. Programozás alapjai 2. (inf.) pót zárthelyi gyak. hiányzás: 2 n/kzhp: n/11,5. ABCDEF IB.028/2.

0. Megoldó Manó 0. Programozás alapjai 2. (inf.) pót zárthelyi gyak. hiányzás: 2 n/kzhp: n/11,5. ABCDEF IB.028/2. Programozás alapjai 2. (inf.) pót zárthelyi 2014.05.22. gyak. hiányzás: 2 n/kzhp: n/11,5 ABCDEF IB.028/2. Hftest: 4 (2,4p) Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot,

Részletesebben

.Net adatstruktúrák. Készítette: Major Péter

.Net adatstruktúrák. Készítette: Major Péter .Net adatstruktúrák Készítette: Major Péter Adatstruktúrák általában A.Net-ben számos nyelvvel ellentétben nem kell bajlódnunk a változó hosszúságú tömbök, listák, sorok stb. implementálásával, mert ezek

Részletesebben

Programozási nyelvek Java

Programozási nyelvek Java statikus programszerkezet Programozási nyelvek Java Kozsik Tamás előadása alapján Készítette: Nagy Krisztián 2. előadás csomag könyvtárak könyvtárak forrásfájlok bájtkódok (.java) (.class) primitív osztály

Részletesebben

Pénzügyi algoritmusok

Pénzügyi algoritmusok Pénzügyi algoritmusok A C++ programozás alapjai Tömbök (3. rész) Konstansok Kivételkezelés Tömbök 3. Többdimenziós tömbök Többdimenziós tömbök int a; Többdimenziós tömbök int a[5]; Többdimenziós tömbök

Részletesebben

Pénzügyi algoritmusok

Pénzügyi algoritmusok Pénzügyi algoritmusok A C++ programozás alapjai Sztringek Osztályok alapjai Sztringek Szöveges adatok kezelése Sztring Karakterlánc (string): Szöveges adat Karaktertömbként tárolva A szöveg végét a speciális

Részletesebben

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library)

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library) Pázmány Péter Katolikus Egyetem Információs Technológiai és Bionikai Kar Bevezetés a Programozásba II 12. előadás (Standard Template Library) 2014.05.19. Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto

Részletesebben

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat Kivételkezelés, beágyazott osztályok Nyolcadik gyakorlat Kivételkezelés Nem minden hibát lehet fordítási időben megtalálni Korábban (pl. C-ben) a hibakezelést úgy oldották meg, hogy a függvény hibakódot

Részletesebben

503.AA Megoldo Arisztid 503.A

503.AA Megoldo Arisztid 503.A Programozás alapjai 2. (inf.) 2. ZH 2017.04.27. gy./l. hiány: / ABCD123 Minden beadandó megoldását a feladatlapra, a feladat után írja! Készíthet piszkozatot, de csak a feladatlapra írt megoldásokat értékeljük!

Részletesebben

Programozás II. 2. Dr. Iványi Péter

Programozás II. 2. Dr. Iványi Péter Programozás II. 2. Dr. Iványi Péter 1 C++ Bjarne Stroustrup, Bell Laboratórium Első implementáció, 1983 Kezdetben csak precompiler volt C++ konstrukciót C-re fordította A kiterjesztés alapján ismerte fel:.cpp.cc.c

Részletesebben

8. gyakorlat Pointerek, dinamikus memóriakezelés

8. gyakorlat Pointerek, dinamikus memóriakezelés 8. gyakorlat Pointerek, dinamikus memóriakezelés Házi ellenőrzés Egy számtani sorozat első két tagja A1 és A2. Számítsa ki a sorozat N- dik tagját! (f0051) Egy mértani sorozat első két tagja A1 és A2.

Részletesebben

Programozás C++ -ban 2007/7

Programozás C++ -ban 2007/7 Programozás C++ -ban 2007/7 1. Másoló konstruktor Az egyik legnehezebben érthető fogalom C++ -ban a másoló konstruktor, vagy angolul "copy-constructor". Ez a konstruktor fontos szerepet játszik az argumentum

Részletesebben

Adatszerkezetek 2. Dr. Iványi Péter

Adatszerkezetek 2. Dr. Iványi Péter Adatszerkezetek 2. Dr. Iványi Péter 1 Hash tábla A bináris fáknál O(log n) a legjobb eset a keresésre. Ha valamilyen közvetlen címzést használunk, akkor akár O(1) is elérhető. A hash tábla a tömb általánosításaként

Részletesebben

500. DD Megoldó Alfréd DD 500.

500. DD Megoldó Alfréd DD 500. Programozás alapjai 2. (inf.) zárthelyi 2009.05.21. gyakorlat: / Érdemjegy: QBX734 () IB319/32. Hftest: Minden beadandó megoldását a feladatlapra, a feladat után írja! A megoldások során feltételezheti,

Részletesebben

Memóriakezelés, dinamikus memóriakezelés

Memóriakezelés, dinamikus memóriakezelés Metódus: függvények és eljárások összefoglaló neve. Memóriakezelés, dinamikus memóriakezelés Nézzük végig, a C++ memóriakezelését. Alapvetően három fő memóriaterületet különböztetünk meg. Végrehajtási

Részletesebben

Járműfedélzeti rendszerek II. 3. előadás Dr. Bécsi Tamás

Járműfedélzeti rendszerek II. 3. előadás Dr. Bécsi Tamás Járműfedélzeti rendszerek II. 3. előadás Dr. Bécsi Tamás 5.3. Mutatók,tömbök A mutató vagy pointer olyan változó, amely egy másik változó címét tartalmazza. A C nyelvű programokban gyakran használják a

Részletesebben

C# Nyelvi Elemei. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei / 18

C# Nyelvi Elemei. Tóth Zsolt. Miskolci Egyetem. Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei / 18 C# Nyelvi Elemei Tóth Zsolt Miskolci Egyetem 2013 Tóth Zsolt (Miskolci Egyetem) C# Nyelvi Elemei 2013 1 / 18 Tartalomjegyzék 1 Object 2 Típusok 3 String 4 RegEx Tóth Zsolt (Miskolci Egyetem) C# Nyelvi

Részletesebben

Programozás II gyakorlat. 6. Polimorfizmus

Programozás II gyakorlat. 6. Polimorfizmus Programozás II gyakorlat 6. Polimorfizmus Típuskonverziók C-ben: void * ptr; int * ptr_i = (int*)ptr; Ez működik C++-ban is. Használjuk inkább ezt: int * ptr_i = static_cast(ptr); Csak egymással

Részletesebben