Portál AbcLinuxu, 30. dubna 2025 14:00
Tiskni
Sdílej:
Kupodivu to jde docela snadno. Nechapu proc se tolik lidi boji C++, ale asi jeste narazim na par pasti.To mi připomnělo Never trust a programmer who says he knows C++.
Akorát u cyklických závislostí musíte dávat pozor, kdy použít silný a kdy slabý chytrý ukazatel.Což je pohodlné asi tak jako španělská bota :) Zvlášť když většina ukazatelů vede uvnitř nějakých knihovních datových struktur, o jejichž implementaci nelze spolehlivě nic předpokládat.
Az bude mozne copy&paste obycejny obrazekTo je otázka prohlížeče, ne jazyka (ten může zůstat, jak je – ne že by se mi JS nějak zvlášť líbil, ale v tomhle je nevinně
O JavaScriptu si porad myslim svoje, slavny Ajax je tu od roku 1998 a porad to je na prd. Az bude mozne copy&paste obycejny obrazek tak o tom mozna zacnu uvazovat.To asi nebude vina Javascriptu :).
Znalosti Win32 API jsou úplně stejně málo přenositelné jako Qt, to si nevybereš.Já si celkem vyberu – Qt je perspektivní a multiplatformní. A Win32 je… škoda mluvit
(Ne)pravidelne zemetreseni v Javovske knihovneJaképak hrozné zemětřesení ve standardní knihovně tě potkalo?
ale na rozdil od jinech zel jsem ochotny ho prijmout protoze ma rozumny duvod. A tim neni fasisticka touha vnucovat vlastni prestavy o "spravnem" programovani.Které třeba?
Java 5. Generalni prepis zakladni veci jako jsou kontejnery podle me neni znamkou kdovijak promysleneho navrhu. Ze to bylo uz podruhe (poprve myslim Ve 2ce) duveru zrovna neprida. Ze to nebylo ani naposled, to uz jenom nasere. Jave viditelne schazi autorita s dlouhodobym pohledem jako je Bjorn nebo BDFL.(Ne)pravidelne zemetreseni v Javovske knihovneJaképak hrozné zemětřesení ve standardní knihovně tě potkalo?![]()
Treba "kazda trida ve vlastnim souboru". Ne ze by to byla spatna praxe, ale... Ja se muzu rozhodnout ze to je spravny pro muj projekt. Muzu si myslet ze to je spravny pro vsechen muj kod. Ale autor jazyka to to vnucuje vsem, ve vsech projektech a za vsech okolnosti.ale na rozdil od jinech zel jsem ochotny ho prijmout protoze ma rozumny duvod. A tim neni fasisticka touha vnucovat vlastni prestavy o "spravnem" programovani.Které třeba?
Java 5. Generalni prepis zakladni veci jako jsou kontejnery podle me neni znamkou kdovijak promysleneho navrhuTady je krásně vidět, že se člověk nezavděčí všem. Někomu vadí že se generiky zavedly hodně zkriplené, aby se zajistila zpětná kompatabilita a místo přepsání se udělaly jen kosmetické změny, jiný brblá že tyto kosmetické a zpětně kompatabilní změny jsou hrozné zemětřesení.
Java 5. Generalni prepis zakladni veci jako jsou kontejnery…A rozbilo ti to nějaký kód, který před 5 fungoval? Takové rozbití se mi v Javě stalo jen jednou (v jiných jazycích jako třeba PHP je to daleko častější) a to když přišel Enum a já měl jednu proměnnou pojmenovanou enum – to samozřejmě nešlo zkompilovat, protože enum bylo od té doby klíčové slovo. Co se týče těch generik (nejen v kolekcích) tak to je skvělá věc, mohla být už dříve, ale aspoň, že je od 5. Je to prostě nová funkce, ale psát si to postaru klidně můžeš.
Treba "kazda trida ve vlastnim souboru".S tím jsem nikdy neměl problém a naopak se mi to líbí (třída se jmenuje jako soubor, dá se v tom dobře vyznat). Java je poměrně jednoduchá a „omezená“ (byť to omezuje minimum* lidí) a to je právě jeden z důvodů jejího úspěchu – ve srovnání s jinými jazyky (C++, Perl, PHP atd.) je snazší číst kód po někom jiném a spolupracovat s ostatníma. Tohle beru jako výhodu, ne nevýhodu. *) např. kdo by potřeboval mít víc tříd v jednom souboru nebo nemít adresáře a balíčky 1:1?
Tak ja to napisu jeste jednou – me "kazda trida ve vlastnim souboru" nevadi a v C++ inklinuju k temuz. A pokud je to optimalni v 99% pripadu, nic mi v C++ nebrani to tak v 99% pripadu delat.jedna trida = jeden soubor je vcelku rozumne pravidlo a spousta lidi k nemu dospeje tak nejak automaticky ale treba k pravidlu adresar = namespace spousta lidi nedospeje. a to je pak radost cist zdrojaky v C#, kde je jeden namespace rozhozeny pres pet adresaru a v jednom adresari je pet namespacu
Kdyz se ten kod generuje, tak je to opruz.Treba "kazda trida ve vlastnim souboru".S tím jsem nikdy neměl problém a naopak se mi to líbí (třída se jmenuje jako soubor, dá se v tom dobře vyznat).
Java 5. Generalni prepis zakladni veci jako jsou kontejnery podle me neni znamkou kdovijak promysleneho navrhu.Žádný generální přepis kolekcí se v pětce nekonal, to je nesmysl. Ale takové JDBC, kua, tam jsou nekompatibilní změny skoro v každé verzi.
Jave viditelne schazi autorita s dlouhodobym pohledem jako je Bjorn nebo BDFL.Plus milión. I kdyby to měl být matlák typu Anderse Hejlsberga nebo toho Bjarna, pořád by to bylo lepší než teď.
Treba "kazda trida ve vlastnim souboru". Ne ze by to byla spatna praxe, ale... Ja se muzu rozhodnout ze to je spravny pro muj projekt. Muzu si myslet ze to je spravny pro vsechen muj kod. Ale autor jazyka to to vnucuje vsem, ve vsech projektech a za vsech okolnosti.Každá veřejná třída ve vlastním souboru. Ale dneska asi není důvod se v javovském projektu orientovat podle adresářů a souborů, úplně stačí podle balíčků a tříd (s rozumným IDE, samozřejmě). Sice mne to taky občas štve, ale tohle je spíš drobnost.
vykonem opravdoveho kodu.To je už v dnešní době z velké části pasé.
musí bohatě stačit za použití dobré knihovny pro sdílení dat mezi vlánkykdyz se divam na vyvoj prog. jazyku tak to vypada spis, ze sdileni dat mezi vlakny je cesta do pekel a bude potreba jazyku, ktere ve jmenu paralelniho programovani budou vyrazne restriktivnejsi nez C++
Pro masivní paralelizaci není potřeba restriktivní programovací jazyk. Je potřeba opatrný programátor.to je stejne kvalitni tvrzeni jako, ze v assembleru se da taky programovat, jenom je potreba opatrny programator. podivej se na erlang nebo clojure
No, není.tady nekdo nepochopil metaforu.
Stejně tak C++ umí přistupovat k proměnným z jiných vláken bez synchronizace.na synchronizaci mas takove bajecne veci, jako zamky, coz je takove ,,goto'' paralelniho programovani. low-level operace, jde to pouzivat, programy funguji, ale casem se z toho stane peklo.
Velice podobné tomu, jak se programuje v Erlangu nebo Clojure, jsou Intel TBB.To se mi az nechce verit, vazne TBB obsahuji treba transakcni pamet?
Používá to C++, umožňuje to všechno, co C++, ale při té paralelizaci je potřeba, aby byl programátor opatrný, co dělá, protože C++ mu dovolí dělat téměř cokoliv.ani opatrnost ti casto nepomuze,... treba do posledniho updatu C++ nemelo definovany pametovy model, proto napsat prenositelnou implementaci bezzamkovych struktur bylo nemozne.
... použití vláken bez nepochopitelných chyb by tímto způsobem jít dosáhnout mělo.Tady vidím obrovský rozpor.
kdybys tohle tvrdil pred 10 rokama, kdy to jeste vypadalo ze procesory se budou zrychlovat do nekonecna tak bych se nedivil, ale rikat to dneska, kdyz uz nekolik let jsou procesory porad na stejny frequenci a moc nahoru uz to pravdepodobne nepujde, tomu teda rikam ignorance....S rychlostmi procesorů to nemá nic společného. Java už dávno není interpretovaný jazyk, JIT kompilátor toho umí opravdu hodně a rozdíl oproti tomu "opravdovému kódu" začnete cítit až od určité poměrně dost vysoké meze.
C++ moc neznam, ale od doby, co znam Common Lisp, k tomu muzu rict jen jedno. Nepochopim, proc nesli cestou plnohodnotneho makro systemu misto sablon.Me prijde, ze to bude mit nejakou historickou pricinu a ze driv makra byla v nemilosti. Od spousty C++ programatoru jsem slysel, ze makra jsou zlo, protoze umoznuji delat chyby, ktere jsou pry spatne odhalitelne. Tipoval bych, ze sablony vznikly jako pokus nahradit makra, jenomze, jak ve spatnem hororu, se tento pokus vymkl kontrole a vzniklo z toho, co vzniklo.
Na jednu stranu je zde filozofie, ze programatorovi by se melo zabranit strelit se do nohy; jenze tim se mu take zabrani psat efektivni kod a to neni vzdycky zadouci. To je filozofie Javy.Oni si programatori vzdycky najdou neco, cim se muzou strelit do nohy. V zadnem jinem jazyce jsem nevidel tolik projektu trpet overengineeringem, jak v Jave.
Od spousty C++ programatoru jsem slysel, ze makra jsou zlo, protoze umoznuji delat chyby, ktere jsou pry spatne odhalitelne.
#include <iostream>
#define ABS(x) ((x) >= 0 ? (x) : -(x))
int main()
{
int x = -3;
std::cout << ABS(++x) << std::endl;
}
Kolik bude vypsáno? std::cout << ABS(++x) << std::endl;
Nás vždy učili na jednom řádku dělat jednu věc. Věci jako ABS(++x) jsou (podle tohoto pravidla), prasárna sama o sobě, ať jde o makro, nebo třeba volání funkce (kde záleží na pořadí vyhodnocení argumentů). Takže tato past může sklapnout i jinde.
x++
, ale s ++x
? Krom toho, mohlo by tam být třeba volání funkce, jejíž výsledek člověk nechce lokálně ukládat. Zavolala by se dvakrát... Mám to odtud, tam mají zla maker shrnutá... Zároveň je ale dodáno, že je člověk přesto občas použije. Imho moc dobré toto faq.
std::cout << ((++x) >= 0 ? (++x) : -(++x)) << std::endl;Odkud je již vidět, kde je zakopán pes.
++x
způsobit problém ve volání funkce... což moc nevím jaký, leda by se to použilo dvakrát po sobě, což tedy už je prasárna i podle mě...
To vím, řeč byla o něčem jiném; o tom, že by mohlo ++x způsobit problém ve volání funkce... což moc nevím jaký, leda by se to použilo dvakrát po sobě, což tedy už je prasárna i podle mě...uvazuj treba:
void foo(int, int); x = 1; foo(x++, x);Protoze poradi vyhodnoceni argumentu neni presne specifikovane (nejcasteji jde ovlivnit volaci konvenci), muzes funkci volat s argumenty (2, 2) nebo (2, 1) a porad to bude korektni. Problem taky muze nastat pokud se prekladac rozhodne preskladavat nebo eliminovat argumenty kvuli optimalizaci, a to se pak hleda hur.
x++;
se dá ukázat a bylo mnohokrát ukázáno na mnohem jednodušších příkladech ++x
volání funkce...
x++
i ++x
?
for
cyklus. Tam se to občas hodí.
V C++ prostě makra k ničemu nepotřebuješ. A když je potřebuješ, tak je něco špatně.Takze treba takove Qt je spatne, kdyz dela veci, ktere se bez hypotetickych maker udelat nedaji? Implementace MOC je napriklad velmi dobry priklad, jak makra v C++ chybi. Nebo takovy SWIG. Nebo.. v podstate pro kazdou aplikaci, kde je treba parsovat C++ by byl dobry makro system uzitecny.
v podstate pro kazdou aplikaci, kde je treba parsovat C++ by byl dobry makro system uzitecny.No to souhlasim... dobrý makro systém by byl fajn
Me prijde, ze to bude mit nejakou historickou pricinu a ze driv makra byla v nemilosti. Od spousty C++ programatoru jsem slysel, ze makra jsou zlo, protoze umoznuji delat chyby, ktere jsou pry spatne odhalitelneTohle bude to kutlurní nedorozumnění. Pokud programátor v Lispu mluví o makrech, tak rozhodně nemá na mysli C preprocesor. Asi největší výhodou Lispových maker pak vidím v tom, že makrojazyk je prakticky totožný s hlavním jazykem, což rozhodně není případ šablon v C++.
V C++ používám preprocesor (kromě deklarací) velmi vyjímečně. Pomocí preprocesoru dokážu stejný kód přeložit pro různé platformy (rozdílné cesty a chování souborů ve windows a v linuxu) či definovat číslo a označení verze překládaného programu až při překladu externím programem.Tohle by imho měl řešit build systém spíš než (samotná) makra. Většina build systémů na to je i vhodnější než pouhá makra. Můžeš v závislosti na systémů includovat celé headery nebo nastavovat include dir, atd... Samozřejmě se přitom ta makra taky občas použijí, neříkám, že ne...
U jednočipů je naprosto kritické, zavolám-li nějakou "funkci" jako skutečnou funkci, nebo ji vytvořím pomocí makra. V prvním případě se uklízí stav procesoru a návratová adresa na zásobník, v druhém případě se vloží do aplikace pouze pár instrukcí procesoru.Přesně na tohle slouží inline, pakliže to daný kompilátor podporuje...
S behem programu to nijak nesouvisi, ani neni nijak zvlast potreba adaptovat kompilator, protoze ten dostava uz (makry prepracovany) zdrojovy kod podle specifikace.No jo, jenže jaký zdrojový kód ten kompilátor dostane není lhostejné. Jestliže kompilátor dostane (například) jeden for cyklus, může to optimalizovat lépe, než když dostane nepředvídatelné houští všelijakých
goto
.
Jestliže kompilátor dostane (například) jeden for cyklus, může to optimalizovat lépe, než když dostane nepředvídatelné houští všelijakých gotoPokud vim, tak optimalizace se stejne vetsionu delaji nad nejakou vnitrni reprezentaci (napr. control flow graph), kde uz je vcelku jedno, zda v programu byl for cyklus nebo smes goto.
když si ale takovýhle konstrukce napíšu v metajazyku a pak je použiju, bude mít kompilátor omezené možnosti je optimalizovat.Kompilátor to nepozná. Kompilátor se ke kódu dostane až po zpracování preprocesorem.
A programator se nedostane k tomu co je skutecnym vstupem pro kompilator.
gcc -E foo.cpp
Myslim, ze deda.jabko tohle dobre vi, ale pro kralyka a ty pod nim je to dobra poznamka. Myslim, ze pointa byla, ze se autori C++ chteli vyhnout C makrum nebo jejich rozsireni, proto s tim meli problem, a Lispova makra bud poradne neznali, nebo je mylne povazovali za stejne spatna, a v neposledni rade take meli problem se syntaxi (jak znamo, Lispova makra vyuzivaji (ne)syntaxe Lispu).Presne tak jsem to myslel.
Myslim, ze deda.jabko tohle dobre vi, ale pro kralyka a ty pod nim je to dobra poznamka.Já vím, že autor Schemika tento rozdíl asi postřehl. Jenom jsem svoji reakci přišpendlil na špatné místo.
C++ moc neznam, ale od doby, co znam Common Lisp, k tomu muzu rict jen jedno. Nepochopim, proc nesli cestou plnohodnotneho makro systemu misto sablon. Oboji vam umozni strelit se do nohy, ale makro system je aspon obecnejsi.Lispovy system maker je dost silne vazany na to, ze nativni lispove struktury (seznamy a symboly) prirozene reprezentuji Lispovy zdrojovy kod. Takze makrojazyk pro Lisp je vcelku prirozene reseni, pro jine jazyky to v podstate znamena navrhnout druhy programovaci jazyk. Jinak lisp-style makra maji take spoustu problemu a napr. ve Scheme lisp-style makra opustili a misto toho maji vice deklarativni (a hure pochopitelny) makrojazyk (alespon tedy v R5RS, R6RS jsem nestudoval). Jinak genericky makrojazyk je urcite uzitecna vec, ale metaprogramovani je obecne slozite a problematicke a mam pocit, ze nejcasteji uziti maker je stejne na obchazeni limitaci jazyka - v C je to nepritomnost generickych konstrukci, v Lispu/Scheme pak nemoznost zmenit namespace volaneho resp. nepritomnost nejake obdoby call-by-reference. Vyuzivat makrojazyk pro tyto pripady zbytecne veci komplikuje, takze rozumne reseni je do jazyka dodat potrebnou funkcionalitu a makra nechat jen na ty veci, na ktere jsou opravdu potreba. Proste pouzivat C++ je IMHO v tomto opacny extrem, kde se, mam dojem, sablony pouzivaji z duvodu nepritomnosti vhodnejsiho prostredku na veci, ktere jsou za hranici obecnosti problemu, pro kterou se sablony hodi.
Lispovy system maker je dost silne vazany na to, ze nativni lispove struktury (seznamy a symboly) prirozene reprezentuji Lispovy zdrojovy kod.Ne nutně – i v jiných jazycích mohou makra pracovat nad syntaktickým stromem kódu. Pokud si pamatuji, tohle umí jak Perl6, tak nějaké rozšíření Haskellu. Čím dál víc mi připadá, že používat jako preprocesor tentýž jazyk (do libovolné hloubky vnoření, samozřejmě) je jediná možnost, která doopravdy dává smysl.
Ako môžu byť kompatibilné bez hrabania na pointre? Neraz som robil stotinkovú aktualizáciu kvôli bugu pri určitom use case, s ktorým som nerátal a musel som kvôli tomu trochu prekopať vnútro triedy. Keďže ale dátovú časť tried väčšinou tvorí opaque pointer nenastane žiaden problém (jedine ak by snáď niekto využíval bug). Zmena implementácie vnútra triedy / pridanie tried / pridanie metód je bezpečná operácia pri ktorej všetko vyrieší linker. Samotné objekty ale linker neporieši. Preto radšej robím s pevnou veľkosťou (32bit / 64bit / ... podľa platformy) objektov.
Ako C++ nie je jazyk pre každého, nerád by som bol ak by sa niekto z C++ snažil urobiť niečo, čo nie je. Je to proste nízkoúrovňový jazyk so všetkým, čo k tomu patrí a kto chce niečo iné má fúru iných jazykov. Kto chce v C++ robiť kvalitný kód musí prejsť dlhou a ťažkou cestou. Ono to trvá kým sa človek naučí používať podmnožinu tak komplexného jazyka ako je C++, ktorú bude často používať. Ak si človek ale zvykne na C++ nie je to o moc zložitejšie ako vo vyšších jazykoch.
Last edit by dolik on 06/24/2010
Zaujímav v roku 2010 porovnávať niečo s už niekoľko rokov nepoužívaným frameworkom (Qt3).
Rovnako zaujímavé porovnávať layout vytvorený v kóde s layoutom v nejakom vlastnom jazyku pre layouty (len tak pre zaujímavosť s Qt si stačí layout naklikať a celé ui uložiť v designéri, ale to nie je tak podstatné).
Takže keď už chcem nejako rozpitvávať spýtam sa ako urobím takú vec ako 3 buttony rovnakej šírky (ak je náhodou na nejakom dlhší text než tlačidlo tak sa samozrejme musí trochu ukrojiť z okolitých tlačidiel / automaticky zväčšiť okno). Kód pre Qt vyzerá asi takto:
QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(new QPushButton("But1")); layout->addWidget(new QPushButton("But2")); layout->addWidget(new QPushButton("Dllllllllllllllllllhy text"));
Nechcem tu teraz Qt nejako chváliť, som jedným z jeho kritikov minimálne kvôli modelom, použitiu int-ov namiesto size_t a pod. Chcem len poukázať na to, aké sú tieto porovnania nezmyselné. Objektívnym kritériom nemôže byť ani tak počet riadkov, ani nejaké na prvý pohľad hneď jasné kritérium, ale len a len dlhodobá práca s frameworkom. Ja si osobne na U++ okrem zjavných nedostatkov nedovolím nič povedať pretože s nim nepracujem dostatočne dlho na to, aby som odhalil nedostatky, ktoré ma budú pri práci zdržiavať.
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.