Egy autodidakta C/C++ tanuló kérdései

Fórumok

A címből kiderül, hogy saját örömömre C/C++-t tanulok mert élvezem (Akarok asm-et is de előbb C/C++). Kitaláltam írok egy sudoku megoldót (mint kiderült utólag az egyik haver programozó azt mondta eddig úgy néz ki amit írtam mit egy kutya bonyolult back-track, szóval feltaláltam a melegvizet, de sabaj élvezem. Soha nem tanultam "mestint"-et), mivel magamnak tanulom kicsit csúnya a kód és nem elegáns de működik. Majd belejövök. Pl nem szoktam különboző álományokat írni, hanem egy nagy állomány, de azt addig optializálom ameddíg bírom. Na szóval a magam stílusában gyak bármit megírok amihez értek. (Mivel fizikus vagyok ez többnyire numerikus matematikai problémákat jelent.) Viszont most kitaláltam hogy szépen is meg akarok tanulni programozni mert így a kódok amit csinálok másnak káosz, csak nekem nem mert én tudom mi mit jelent (legalábbis rövidtávon de mindík kommentezek).Na első kérdés.

Miben jobb a muatótömb mint a statikus? (Meg tudom mind a kettőt csinálni, mert a könvben amiből tanultam le van írva hogy hogyan kell de semmi magyarázat hol jobb miért jobb, vagy rosszabb stb.. annyit tudok hogy a mutatókból definiált az futási időben felszabadítható. De ezen kívül?)

Azt is olvastam hogy a mutatótömb elérése gyorsabb mutatókon keresztül. Tudom, hogy hogyan kell ezt megvalósítani cím/adatátadással p=&a és a társai de miért gyorsabb? Szertném érteni, hogy ki tudjam használni, és ne csak a saját örömömre írjak bonyolutabb kódot.

Másik szeretm kihagyni a segédváltozókat, ezért néha orbitális hosszú kifejezéseim vannak mint pl:
oszlop [vizsgalt_szam][0]= ++oszlop[vizsgalt_szam][oszlop[vizsgalt_szam][0]];
(ez a rövidebbek közé tartozik még :D csak most a sudoku-megoldómban ez a leghosszabb) Mennyire húzós dolog ez? Nyerek vele sebességet? Vagy csak túlbonyolítom a problémát.

Minek írjak valamiből fügvényt, ha nem kell x-milliószor használni, ha valamit még egyszer végre kjell hajtani kivág beilleszt, és kész (Ezt azért kérdezem mert a könyvemben a példék egy két soros kiiratásból is külön függvényt csinál, szerintem csak tulspirázás.). Tudom hogy hízlalja a kódot, és nagyob lesz a futtatható állomány, ami nagyobb az meg majdnem bioztos hogy lomhább is, de én nem csinálok külön függvényt, csak akkor ha az megérdemli. Pl Az emített sudokumegoldómban van 4 fügvény egy rosta, egy tipp, egy ellenőrző és egy visszalépő fügvény ezekt ismétli addig amíg van üres rekesz. Ha meg telerakomm mindenből fügvény visszatéréelemzés.... Nehogy már egy printf / cout ne fusson le sima kiratásnál a képernyőre mit ellenőrizgessem, hogy mivel tért vissza. Ami megérdemli azt ellenőrzöm.

Hirtelen elfogytak a kérdések de szarintem lesz még. Most kicsit úgy érzem magaam mint akinek azt mondják, hogy ne pofázz csináld.

Előre is köszi a segítő válaszokat.
Krisztián

Hozzászólások

A mutatos kerdesekre akkor talalod meg a valaszt, ha majd assemblyt is tanulsz, es megnezed a generalt kodot asm-ben. Igy kicsit nehez lenne elmagyarazni, mikor miert gyorsabb egyik vagy masik, es sokmindentol fugg is.

Fuggvenybe meg akkor rakunk vmit ha azt tobb helyen hasznaljuk, es igy eleg egy helyen modositani a kodot ha pl. hibat talalsz benne vagy uj feature kell. Vagy ha ettol atlathatobb lesz a kod (lasd mplayer.c ;)). Nyilvan nem kell mindne printf-et kulon fuggvenybe rakni, azt csak a konyvek/infotanarok szoktak :)

A'rpi

Szerintem pont eljött az ideje, hogy elkezdj ismerkedni az objektum orientált programozással.

szerintem maradjunk annyiban hogy nagy, lassu es karbantarthatatlan programot barmilyen nyelven lehet irni. sajnos ez megforditva mar nem feltetlenul igaz, de atgondolt tervezessel, jopar ev rutinnal siman lehet c++-ban is gyors, kicsi es szep kodot csinalni. Ha belegondolsz a member valtozok elerese c++-ban egy pointer invokacioval kerul tobbe (this) mint c-ben a globalis valtozo (ez utobbi indokolatlan hasznalataert meg siman kinpadra vonatnek barkit), sima lokalis valtozo, vagy fuggvenyparameter elerese pedig pontosan ugyan olyan gyors C-ben mint a member valtozok elerese c++-ban. (stacken levo valtozok is pointeren (BP x86-on) keresztul erhetoek el. Raadasul az hogy nem minden egyes adatot fuggvenyparameterkent adsz at hanem adott esetben ezeket member valtozokban tartod, megsporolja azt az idot amig a stackre masolnad oket fuggvenyhivas elott, szoval letezik olyan eset amikor meg gyorsabb is az ojjektum orientalt megkozelites.

Szoval az hogy TE nem tudsz objektum orientalt nyelven gyors es atlathato kodot irni az a TE tudasodat minositi es nem az objektum orientalt nyelveket, plane nem a C++-t.

regparm, a stack mar divatja mult :)

hany parameter fel el regiszterekben? Egy atlagos kod vegrehajtasa kozben hany felesleges regiszter alldogal kihasznalatlanul?

Ja es struct is tudja ezt :)

ha valtozokent adod at akkor ugyan ugy az egesz bemasolodik a stackre. ha meg pointerrel, akkor ugyan ott vagy mint ha class lenne. Csak rondabb es atlathatatlanabb.

Egyeb erv?

Fejben átláthatónal nagyobb rendszereknél (a fejben átlátható mérete egyénenként változik :-)) az optimalitásnál sokkal fontosabb az átláthatóság, szeparáltság, meg ilyenek.

Azt, hogy miért kell minden ismétlődő kódot kiemenlni külön függvénybe itt elmagyarázzák: http://en.wikipedia.org/wiki/Don't_repeat_yourself

Csak félve írom le, mert épp azt akarom sugallni, hogy ilyesmivel nem kell törődni, de: A kész program nem feltétlenül lesz nagyobb attól, hogy több függvényt írsz. A fordító simán inline-osíthatja a függvényt akár (ami azt jelenti, hogy a függvény tartalmát a fordító copipészteli be, és tuti nem hibázik ellentétben az emberrel).

Szinte soha nem érdemes optimalitásra törekedni alacsony szinten, inkább az algoritmusokra és adatszerkezetekre kell koncentrálni. Jó adatszerkezet és algoritmus szüli a hatékony megoldást.
Tehát:
Jól strukturált prototípust érdemes csinálni, amit (ha szükséges, de csak akkor) profilozni lehet és csak a szűk keresztmetszeteket optimalizálni. Az optimalizálás is legtöbbször adatszerkezetek átírását jelenti, nem függvények összevonását.

Általában ha egyből csak az optimálist vagyunk hajlandók leírni a vége az lesz, hogy a rendszer nem készül el. Ennél jobb egy szuboptimális működő megoldás.

Ezen a stádiumon szerintem mindenki átesik amúgy. Egyszer azonban rá fogsz döbbenni, hogy amit most átlátsz, azt egy hónappal később már talán nem, és hogy átírni valami alapvetőt valószínűleg nem könnyű a programodban. Szerintem makacs embereknek a saját bőrén kell ezt megtanulni :-). Én is makacs voltam...

a kopipészt rossz gyakorlat,
használj segédváltozókat,
kerüld a triviális kommentezést,
egy-két oldalnál hosszabb blokkot ne írj,
C++-ban használj const referencia függvényargumentumokat

Mindenek előtt _mentsd el_ a jelen verziót, mert az működik! Nagyon könnyű elbóklászítani a forrást, aztán meg hiába a sírás-rívás, ha nincs mihez visszatérni.
Most még nem érdemes agyalnod ezzel, de nagyobb programoknál, amikor egy-egy ilyen 'részleges átírás' több napon át is tarthat, ezért is érdemes valami verziókövető rendszert használni. De mindent a maga idejében, úgyhogy egyelőre jó kódpucolást :) !

A "példányokból álló tömb a mutatókból álló ellenében" kérdéshez annyit tennék hozzá, hogy:

1., Elérés szempontjából a példányok tömbje egy hangyacsápnyit gyorsabb ugyan, mert a példányok tagjainak elérésére nem jön még rá a mutató kiolvasása, de ez messze nem éri meg, mert:

2., A mutatókból álló tömböt könnyebb manipulálni, ugyanis pl. egy elem törlésekor nem az összes utána lévő példányt kell előrébb mozgatni eggyel, hanem csak az összes utána lévő mutatót, ez pedig kb. annyiszor gyorsabb, mint ahányszor több memóriát foglal egy példány mint egy mutató. Ugyanez igaz pl. beszúráskor ill. még határozottabban a tömb rendezésénél vagy egy tömbelemnek egy másik tömbbe való átmozgatásakor is.

3., Ha a tömb elemeit nem annyira indexelve, mint inkább csak sorban kell elérned, akkor a mutatókból álló tömb végét jelezheted az utolsó utáni elem NULL-ra állításával, így nem kell külön nyilvántartanod (és esetleg paraméterként átadnod) az elemszámot is.

4., Ha már C++-t használsz, és a tömbödben objektumok mutatóit tartod nyilván, ezek nem feltétlenül kell, hogy azonos típusúak legyenek, elég, ha leszármazási viszonyban vannak egymással. Pl. van egy ember_t tipusod (név, szig.szám), ebből származik egy programozo_t típus (ember_t + ismert nyelvek), akkor egy 'ember_t **csapat' tömbben lehetnek sima emberek és programozók mutatói is, viszont egy 'ember_t *csapat'-ban csak sima emberek lehetnek, mert a két objektumtípus példány-mérete értelemszerűen különbözik.

5., Bár ez már kisebb jelentőségű, de egy példányokból álló tömb egyetlen nagy folytonos memóriaterületet igényel, míg a mutatókból és mutatott példányokból álló felépítmény több kisebbet, így elhelyezhető a címterületed kisebb szabad réseiben is (szemben az előbbivel), így eredményezhet jobb memóriakihasználást, bár ez -mint mondtam- esetleges.

Egyelőre ennyi jut eszembe :).

A C-ben minden függvény! Ha akarsz függvényt írni, ha nem. Ha egy kódrészletet kétszer kell végrehajtani és több egy sornál, akkor már megéri fügvényt írni rá. A visszatérési értéket meg nem kell mindig ellenőrizni, sőt van olyan is, hogy nincs visszatérési érték, akkor void típusú függvényt írsz, ami tulajdonképpen eljárás.
A függvényekre bontás nem csak a hatékonyságot növelei, de a program átláthatóságát is javítja. Nem véletlenül találták ki a struktúrált programozást. De ha már C++-t is említetted, akkor az OO elveket is megnézhetnéd! Hidd el nem hülyeség és nem csak arra való, hogy a programozó fölöslegesen szenvedjen vele.
Ha egy program csak 10-20 sor, akkor persze nincs jelentősége, de nagyobbacska programok esetében már meggondolandó a világos átlátható forráskód készítése.
És ez nem csak a C-re vonatkozik.

A megjegyzésedhez pár gondolat:

C++-ban különösen fontos, hogy átlátható kódot írjunk. A segédváltozókat a compiler nagy valószínűséggel kioptimalizálja, valamint léteznek inline függvények és interproceduralis optimalizáció is... Szóval inkább írjál csak függvényeket és osztályokat, csak legyen érthető a kód.

Hosszú távon az átláthatóság a legfontosabb. Én azon a véleményen vagyok, hogy a nem átlátható kód csak a performance kritikus helyeken megengedett, viszont ott erősen kommentezni kell.

A C++ tanuláshoz van pár javaslatom:
- http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html
- S.C. Dewhurst: C++ hibaelhárító

Ebből a két könyvből véleményem szerint ízlésesen meg lehet tanulni programozni, ha az ember alkalmazza a gyakorlatban az olvasottakat. Persze a legjobb elmenni nigger-programozónak két-három helyre, ott úgyis lát (és ír) az ember elég rossz és jó kódot ahhoz, hogy legyen ízlése, és az általad feltett kérdésekre tudjon válaszolni... :-)

A másik dolog: a bejegyzésed olyan stílusban van fogalmazva, hogy alig bírtam magam átrágni rajta. Nagyon nehezen olvasható post, annyi szent. Kövezzetek meg, de szerintem van összefüggés aközött, hogy mennyire jól írunk magyarul és hogy mennyire jól programozunk...

Csak egy példa:

"Másik szeretm kihagyni a segédváltozókat, ezért néha orbitális hosszú kifejezéseim vannak mint pl:
oszlop [vizsgalt_szam][0]= ++oszlop[vizsgalt_szam][oszlop[vizsgalt_szam][0]];
(ez a rövidebbek közé tartozik még :D csak most a sudoku-megoldómban ez a leghosszabb) Mennyire húzós dolog ez? Nyerek vele sebességet? Vagy csak túlbonyolítom a problémát."

Az idézett magyar mondat pont annyira nehezen kódolható és félreérthető az emberi szemnek, mint az idézetben szereplő kódrészlet... (Ráadásul a helyesírás szabályai szerint erősen syntax erroros.)

Ez igaz, hogy a fogalmazókészségem, nem valami topp, és elég masszivan dyslexias, és dysgafias vagyok, tehát a fogalmazásom, és arra amire gondoltam igen komoly külömbségek szoktak lenni. Halál komolyan néha én sem tudom mit akartam leírni. De valahogy ez a programozásban nem szokott zavarni. A menetet kitalálom, hogy mit hogyan kell, és utána bepötyögöm, amit meg elírok a fordító kidobja hogy hülyeséget írtam. Pl nem használok olyan változónevet hogy d/b a/o hanem relatíve hosszú neveket, és ott kevesbbet tévedhetek úgy hogy az elírásokból származzon.

Ez átmeneti változóneveknél (ciklusváltozó, ilyes) felesleges, és fárasztó is. Ha egy változót sokszor használok, a francnak sincs kedve leírni hogy mutatokat_tarolo_tomb, inkább hogy mtt. De a nagyobb programoknál te is rá fogsz jönni, hol érdemes rövidíteni, és hol nem.

A kilométeres kifejezésekre: Két hét múlva vedd elő az ilyen kifejezéseket, és próbáld meg értelmezni. Két hónap múlva ismét. Ha megy, használd. Ha nem, akkor rájöttél a segédváltozók hasznára.

Ha gyorsan akarsz belejönni a C++-programozásba (és el akarod kerülni a hibát, hogy C++-ban írsz C-programot), akkor ajánlanék még egy könyvet:
Koenig - Moo: Accelerated C++ (C++ In-Depth Series, ed. by Bjarne Stroustrup, AT&T Inc.)

ez szerintem eléggé fekszik a fizikus türelmetlenséghez (azaz, már az első nap működő programot akarunk írni), a részletek megértéséhez meg elkerülhetetlen a C++-biblia:

Bjarne Stroustrup: A C++ programozási nyelv I-II. (Kiskapu könyvkiadó - Addison-Wesley - AT&T, szerintem szintén a C++ In-Depth Series).
Mindkettő előnye, hogy rögtön objektumorientált programozással kezdi, és az STL-t is használja.

C-hez a klasszikus:
Kernighan - Ritchie: A C programozási nyelv (Műszaki könyvkiadó), az új kiadás szépen ANSI C-t használ.

Még egy tanács: kezdj C++-szal. A C nagyon remek, ha már van programozási gyakorlatod. A következő lépés lehet az ASM (bár, a C egyesek szerint egy "hordozható assembly" :-) ).
Ha numerikus számolásokat akarsz írni, akkor az áttekinthetőség marha fontos; nagyon nehéz egy hosszú programban képlethibát keresni. Ebben a C++ sokat segít. Ehhez is tudok javasolni egy jó könyvet:

Press - Teukolsky - Vetterling - Flannery: Numerical Recipes in C++ (Cambridge University Press). Tartozik hozzá egy kis Example Book is, azt is érdemes nézegetni.
A NumRec nem a legmodernebb, legspécibb numerikus módszereket írja le, de jól használható, általános módszereket, tűrhető (de azért áttekinthető, nem túlbonyolított) implementációval. Szerintem egész jól használható (bár, egy idő után magad is látni fogod, hogy hogy lehetett volna egy kicsit még jobban megcsinálni, kihasználva az OOP előnyeit).

Még egy fontos dolog: ne hidd azt, hogy egy kupac könyvet meg kell tanulni, hogy C++-ban programozhass. Minél hamarabb neki kell esni, és programokat írni a már meglevő tudásoddal, attól lesz sikerélményed, ami fenntartja a lendületedet.

Igen, én is fizikus vagyok. Amit leírtam, tapasztalatból írtam. Én BASIC-kel kezdtem, C-vel folytattam, majd C++, Fortran (utóbbi csak néha, ha Fortran programhoz kell hozzáfejleszteni).

Az Accelerated C++ könyv előnye, hogy megmutatja, hogyan lehet szépen, kezdőbarát módon C++-ban programozni, lépésről lépésre, úgy, hogy már rögtön az elején használható programokat írunk.

A Numerical Recipes előnye, hogy sokszor az, vagy majdnem az van benne, amire nekünk szükségünk van, még ha néha nem is használja ki eléggé a C++ adta előnyöket.

Ne kezdj C++-szal!
A C++ rohadt nehéz nyelv. Igazából ez a legnagyobb hibája, nem kezdőbarát.
Kezdő esetében gyakori, hogy egy 1 oldalas kód 3 oldal hibát generál. (Ha template is kerül a kódba, akkor 15-öt)
Ez megöli a lelkesedést. :)

Persze a C sem igazi első nyelvnek, mivel nem erősen típusos, egy csomó hiba nem derül ki fordítási időben...
Én mégis azt ajánlanám, hogy inkább C-ben kezdj. Sokkal gépközelibb, és utána egyszerűbb megérteni a C++-t is.
Egy kis asm sem árt, de elég annyi, hogy megértsd, hogyan működnek a dolgok. A mutatók egész új színben fognak feltűnni. :)
"Bjarne Stroustrup: A C++ programozási nyelv I-II."
Jó könyv, és nagyon részletes, minden elsőre logikátlannak tűnő dolognak megtalálni benne a magyarázatát.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Erről vitatkozhatnánk napestig, és nem jutnánk dűlőre. Nekem egy alap C simeret után a C++ sokkal könnyebb volt. Mindkét nyelvnek van előnye és hátránya is. Ismerje meg az alapokat, és döntse el hogy melyik nyelv áll a gondolkodásmódjához közelebb. Nekem python, java után a C++ könnyebb volt.

Velem nem fogsz erről vitázni, mert én egyetértek veled. :)

A C++ többek között azért nehéz elsőre, mert rengeteg új dolog van benne a kezdő számára, és rengeteg furcsa, megjegyezhetetlennek tűnő szintaktikai szabály van, ami csak jóval később lesz érthető és evidens.

Ezért érdemes C-t használni egy kicsit, hogy pl az embernek a new/delete ne okozzon fejtörést, hiszen megszokta a malloc/free-t...
C-ben tehát magtanul struktúráltan programozni.
Egy kezdő C tudással meg lehet próbálni az OO-s C++ gondolkodást, és ekkor már könnyen emészthetőek a referenciák, mutatók, stb.

Másik lehetséges út a Java felöl adódik, ahol megtanult OO-an programozni, így már "csak" a mutatókkal, new/delete mókákkal, és egyéb hardware közeli dolgokkal kell megküzdeni.

Nekem ez a kevésbé tetsző út, mivel nagyon sok kezdő aki Java-val kezdett, szörnyen rossz/lassú kódot produkál (már Java-ban is), és ezt a beidegződést hozza magával.
Míg ha valaki C-ben kezd, az megszokta, hogy a gép szintjén gondolkozzon, ennélfogva tudja mikor kell listát, és mikor tömböt használni, és jobban érzi, hogy hogyan is működnek az STL-es eszközök.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

++

Ahogy nálunk tanítják az egyetemen:
1. félév: párhuzamosan C és assembly (C-hez könyv passz, assemblyhez: Máté Eörs - Assembly Programozás; Andrew S. Tannenbaum: Számítógép Architektúrák, 2. kiadás -- az utóbbi ahhoz kell, hogy értse az ember, hogy mi a francot is csinál)
2. félév: Az OOP bemutatása Java-val
3. félév: C++ keményen + algoritmusok és adatszerkezetek tárgyalása

Ahogy kezdünk belemélyedni a számítógép hardverének tárgyalásába, egyre jobban úgy gondolom, hogy anélkül nem lehet programozni.

---------
"Ha igazat mondasz azt végig unják, ha feldíszíted azt jól meg dugják"
szerény blogom -- új címen!

Ha értő módon olvasod a 10 oldalas hibaüzenetet, akkor általában hamar kiderült, hogy mi okozta (az én tapasztalatom, pár év C++-ban végzett numerikus számítás után, hogy az esetek 95%-ában az első hibaüzenet mutatja meg a bajok forrását. Ez persze arra az esetre vonatkozik, hogyha a template-eket nem te írtad, hanem azokat készen vetted át. De épp ezért ajánlottam a fizikus munkához eléggé fekvő Numerical Recipes-t. Szerintem amúgy is, eleinte jobb nem túl sok template-et írni, az eléggé felrobbanthatja a kódot, ha az ember elszúrja.

A másik, hogy képlethibát említettem. Azért csak áttekinthetőbb, hogy tényleg a kivánt egyenlet van-e a programodban, ha egy mátrixszorzás nem úgy néz ki, hogy


int i,j,k;
double *c;
c=(double *) malloc(n*n*sizeof(double));
for(i=0; i<n; i++) for(j=0;j<n;j++){
   c[i*n+j] = 0.0;
   for(k=0; k<n;k++) c[i*n+j] += a[i*n+k] * b[k*n+j];
}

(és itt még a mátrix tárolására a legkőbaltásabb módszert használtam, igazából egy struct-ba kellene tenni, ami tárolja az oszlopok és a sorok számát, egy double**-ot, és írni egy függvényt, ami lefoglalja egyben az egészet, majd berakja a double**-ba a sorok 0-dik elemének a címét, etc., egy másikat pedig, aki fel tudja szabadítani, és NULL-lá teszi a mutatókat...) hanem úgy, hogy


Mat_DP c=a*b;

A numerikus programozás szerintem sok mindenben eltér a programozás egyébb ágaitól, nem annyira a nyelv trükkös dolgain (pl. template-ek) van a hangsúly, hanem az áttekinthetőségen. (És egy türhető library használatán.)

Egyébként szerintem sem ideális kezdő nyelv a C++, de még mindig inkább az, mint a C.

Tudod mi ezzel a gond?

Ha leírja egy kezdő, hogy x=A*b+c akkor nem tudja mi történik. Nem tudja miért lassabb ez mint a C-s megoldása ugyanennek a képletnek, és miért kell hozzá több memória...

Ha meg ne adj isten egy fejlett expression template-es matrix libet használ, akkor tud aztán igazán nem hatékony kódot írni, mivel nem tudja, hogy mikor és miért kéne mégis segédváltozót használnia...

Szerintem ezért fontos, hogy az ember C-ben (vagy Fortranban :) ) küzdjön egy kicsit, és akkor fogja érteni és értékelni igazán a C++ lehetőségeit, és hátulütőit is.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

A C++ nagyonis kezdőbarát, mert nem enged rossz beidegződéseket.

"Persze a C sem igazi első nyelvnek, mivel nem erősen típusos, egy csomó hiba nem derül ki fordítási időben..."

Ugye viccnek szántad, hogy a C++ nyelv erősen típusos? Mert csak kevesebb baklövést enged meg, de még van hova fejlődnie (a C-vel kompatibilis akart lenni, és ez nagy korlát a típusbiztonság terén).

"(és el akarod kerülni a hibát, hogy C++-ban írsz C-programot)"
"nagyon nehéz egy hosszú programban képlethibát keresni. Ebben a C++ sokat segít."

C++ debugolni halal manapsag. (nincs jo eszkoz szvsz)
Ha kihasznalod C++ minden szarat es elkoveted egy numerikus feladtanal ezt akkor azt latod, hogy kodod kurva nagy let kiurvara mindenre jo csak arra nem amire kene, es napokig keresed hol rontotad el, ha meg kezdo vagy akkor meg roszabb.

En filozofiam forditott, C elemek primary, es ha oriasi ingerenciad van akkor C++ elem.

Pár gondolat:

Stílust nem nagyon lehet tanulni. Persze jó könyvekből, leírásokból, esetleg más forrásából jó ötleteket lehet meríteni, de a gyakorlat az, ami igazán megtanít.

Kezdetben mindenki gányol. Pl. ír egy backtracket Sodoku megoldóhoz. Aztán szeretné megoldani a 8 (vagy n :) ) királynő problémát, és a semmiből ír egy másik backtracket. Közben feltűnik neki, hogy jééé, ilyet én már írtam valahol, és jön a copy-paste, meg a változó átnevezések, hogy minden stimmeljen.
Aztán lassan rájön, hogy ezt megírhatná általánosan is...

Az már fél siker, ha érzed, hogy gányolsz, és keresed, hogy lehetne szebben. Hidd el, megtalálod idővel. :)

Mutatótömb, statikus:
Nem érdemes azon agyalni melyik gyorsabb. Minimális a különbség. Már ha van. Szerintem egy mai out-of-order végrehajtású procin nem is mérhető...
Használj statikusat, ha lehet. Egyszerűbb, átláthatóbb.
Ne használd, ha nem lehet, mert pl.: sok helyet foglal egyben, dinamikusan változik a mérete vagy cserélgetned kell az elemeket.
(Egyszerűbb/gyorsabb ugyanis két mutatót megcserélni, mint két structot)

Segédváltozók:
Használd őket. Általában pont az a lassabb, ha nem használod.
Ugyanis ha egy kifejezést kétszer/többször írsz le, ahelyett, hogy segédváltozóba raknád, előfordulhat, hogy a fordító nem veszi észre, hogy megegyeznek, és kétszer számolja ki...
Ugyanakkor, ha egy segédváltozót használsz, de csak egyszer (főleg, ha const az illető változó), akkor esélyes, hogy a fordító kioptimalizálja.
Egyébként majd rájössz, hogy a sebességnél sokkal fontosabb az átláthatóság. (Knut szerint a túl korai optimalizáció minden baj gyökere. :) )

Függvényt két dolog miatt ír az ember:
Többször használja ugyanazt a kódrészt, és/vagy átláthatóbbá akarja tenni a kódot. Én ha már kétszer leírok valamit, és esélyes, hogy lesz harmadik alkalom, már elgondolkozom, hogy nem kéne-e függvényt írnom rá.
Ne felejtsük el, hogy a fv hívásnak minimális költsége van. Egy tízbilliószor lefutó ciklusban ha a fv egyébkén alig csinál valamit, már lassító tényező lehet.
Két megoldás van:
C++: inline fv
C: macro

A fordító egyébként szokott saját hatáskörben inline-osítani, amitől a kód nagyobb lesz, viszont ideális esetben gyorsabb.

Még egy utolsó megjegyzés:
Ne keverd a C-t és a C++-t. Igaz ugyan, hogy a C++ 95%-ban felülről kompatibilis a C-vel (bár nem az új szabvánnyal), de két különböző nyelvről beszélünk, egészen más gondolkodásmóddal.
Ahogy hallgatlak, te C-ben próbálsz programozni.

Sok sikert.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Igen eddig abban tanultam, de egyre inkább a C++ ami dominál, gondoltam kihagyom a lépést és kezdem a modernebbel. Ezt mondjuk nem tudom objektíven megítélni, de mintha a C kihalóban lenne ha lehet ilyet mondani a C++-hoz képest. (De lehet hogy ez marhaság amit mondtam, akkor bocsánat a C-től).

Azért azt nem állítanám, hogy a C kihalóban lenne. :)
(Linux, Gtk, Gnome mind C-s projectek)

Bizonyos területeken a C majdhogynem egyeduralkodó, bár ezekre a területekre is be-betör a C++, mivel kb 5%-os teljesítménycsökkenésért (ami a kivételkezelésből adódik, és kikapcsolható) rengeteg kényelmet tud nyújtani.

A C++ nagy előnye más OO nyelvekkel szemben, hogy miközben elvont objektumokkal dolgozunk benne, ha szükséges "le tudunk menni" a hardware szintjére mint C-ben.

Szerintem az egy jó módszer, ha az ember C-vel kezd, trükközik a mutatókkal, használja a malloc/free-t, és megold egyszerűbb dolgokat.
Viszont amikor úgy dönt, hogy jó lenne már nem csak a konzolra irogatni, akkor érdemes C++-t tanulni, mert az objektum-orientált rendszerek mintapéldája a GUI.

Sokan nem értenek talán egyet velem, de szerintem C-ben GTK-val küzdeni teljesen értelmetlen.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Nem feltétlen. Az, hogy kihasználod a << operátort, még nem jelenti, hogy OOP programozol szvsz. Vagy te a heloworld-öt eleve class-nak írod meg? Mert akkor igen, el tudom képzelni, hogy OOP szerint írod meg.

A C++ Hello World amit én ismerek az ez:


#include <iostream>
using namespace std;

int main() {
    cout << "Hello world!" << endl;
}

Ebben én nem nagyon látok OOP szemléletet, de adj elém nagyítót.

Mint mondtam: "Sokan nem értenek talán egyet velem". :)

Igazábol mondj egy okot ami megmagyarázza, hogy miért küzdjek C-ben egy "objektum-orientált elvű" GUI-val, ahelyett, hogy egy valóban OO nyelvvel tenném ugyanezt.

Egy okot ami nem az, hogy "jó vagyok C-ben, és semmi kedvem új nyelvet megtanulni".

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Mert az Objektum orientált grafikus felületek nagy része a meleg vizet újra és újra feltalálja. Mert az ilyne grafikus környezetekhez tartozó kód fordítása időigényesebb a C-s társánál.

Természetesen ízlések és pofonok. Valószínű hogy én sem fogok Gtk-val szopni, de nem azért mert C alapú, hanem mert számomra bonyolult, és ezt be is vallom.

"Mert az Objektum orientált grafikus felületek nagy része a meleg vizet újra és újra feltalálja."

Most vagy félreértelek vagy nem értem hogy jön ez ide.
Nem az a kérdés, hogy hány OO GUI lib van, vagy hogy ezek mennyiben különböznek, illetve mennyire volt értelme elkezdeni őket fejleszteni.

A kérdés az, milyen racionális okom lenne nekem mint (kezdő) fejlesztőnek, hogy Gtk-t használjak C-ben, valamely OO-s nyelv+lib helyett. (C++ + Qt, C++ + gtkmm, C++ + wxWidgets, C# + ...)

"Mert az ilyne grafikus környezetekhez tartozó kód fordítása időigényesebb a C-s társánál."
Ez nem szempont, mert sokkal kevésbé számít az, hogy mennyi idő alatt fordul, mint az, hogy a fejlesztőnek mennyire kényelmes.
Egyébként sincs nagyságrendi különbség.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Egy okot ami nem az, hogy "jó vagyok C-ben, és semmi kedvem új nyelvet megtanulni".

Oriasi tevedes , ismerem C++. (eleg sok nyelv es paradigma melett)

Mezei GUI alkalmasnal nem mondtam, hogy nem jo OO nyelv, sot hangyapucanyit kenyelmesebb megfelelo eszkozoket hasznalva.
GTK# ot itt is gyakran javaslom mezi GUI-s alaklmazashoz.

Félreértesz, nem akartam személyeskedni. Tény, hogy sokan C-ben profik, számukra kézenfekvő a GTK. De ezen kívül nem nagyon tudok érvet a GTK mellett, különösen nem egy kezdő számára...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Sztem első nyelvnek jó a C, aztán Java majd C++. :)

Sokminden elhangzott a seged valtozokrol, esete valogatja, hogy gyorsabb vagy lasabb kodot generel. (felismer -e a fordito optimalizlasi lehetosegeket .. etc)
Az esetek tobsegeben jobb a seged valtozo.
- ketszer ne szamoltasd ki ugyan azt inkabb seged
(gcc esetben fugvenyknel, ha olyan fugvenyt irsz ami adott bemeno parameterre mindig ugyan azt a viszaterese ertket adja celszeru const nek joloni (__attribute__((const))), ez tovabi optimalizacios lehetesegeket ad a forditonak. (es nem kell seged))
- ne irj ciklust keves elemszmra (<4) (Ha ciklust irsz keves muvelettel 1-2 utasitassal, jobb inkabb tobb utasitas kevesebbszer lefuto ciklus altalban)
- pointer seged valtozo matrix muveletknel sem mindig celra vezeto (see AMD Optimalization guide)

Szerintem az átláthatóság egy hangyacsápnyi előnyt élvez a performanciával szermben. Borzasztóan nem tud érdekelni, hogy mennyire gyors egy kód, ha másnap ugyanarról a sorról nem tudom 3 másodpercen belül megmondani, hogy mit csinál. Inkább több segédváltozó, mint hogy egy darab átláthatatlan kód, amiről fogalmam sincs hogy hogyan működik.

Kevés elemszámra ciklus: esete válogatja. Én mondjuk nem szeretek egy sort kettőnél többször megismételni ha nem muszáj. A háromtól már ciklusra ráng az ujjam. A négynél nem tudok uralkodni magamon, és leírom a ciklust :). De természetesen ha változik egy icipicit is a kód, csak ezért nem fogok ciklussá alakíthatóságot keresni benne, akkor copy-paste, és a megfelelő helyeken módosítom.

Konstans hosszú ciklusokat elvileg a fordító ki szokott "görgetni". Vagy akár meg is tehetné. :)
Out-of-Order végehajtásnál meg úgyis úgy veszi a proci, hogy ciklusban marad az ember, egyedül az utolsó lefutásnál van gond, így minimális értelme van nem ciklust használni.

Igazábol akkor van értelme, ha át is rendezzük a ciklusmag utasításait, hogy kevesebb legyen a cache-miss, meg az adatok a regiszterekben legyenek mire kellenek...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o