van különbség? -konstruktor

 ( Koli | 2010. március 2., kedd - 0:01 )

Sziasztok!

Ha csinálok egy class-t (mondjuk T), aminek a konstruktora nem kér semmilyen paramétert, akkor mi törénik pontosan ennél:

T példány;

és ennél:

T példány();

Mi a különbség?

Köszi!

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Hehh... a

T peldany();

tulajdonkeppen egy fuggvenydeklaracio. Nemreg futottam bele en is, es greenvirag jott ra - magatol.

Na igen, aki ezt kitalalta... Jo, oke, az eloredefinialas miatt kompromisszumot kellett kotni, de... akkor inkabb ez az egesz szintaxis ne johessen letre. T x = T();
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

"de... akkor inkabb ez az egesz szintaxis ne johessen letre"
Miert is ne?

Mert totalisan ertelmetlen.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Mi az ertelmetlen benne?
Ez C++, nem java vagy pascal..

Nem mas nyelvek alapjan ertelmetlen, ugy en bloc. Mit keres egy tipus csak ugy onmagaban, standalone? Mondjuk T. Szamomra sokkal tobbet mond az, hogy T() mint az, hogy T. T akarmi is lehet, egy valtozonev is. A valtozonevek kisbetuvel kezdodnek - de hopp, ez egy konvencio, akar maskepp is lehet.
Object x; - ennek egy inicializalatlan erteku eloredefinialt valtozonak kene lennie, es az x.someMethod()-nak nagyon csunya vegenek kene lennie.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

"Object x; - ennek egy inicializalatlan erteku eloredefinialt valtozonak kene lennie, es az x.someMethod()-nak nagyon csunya vegenek kene lennie."

Ez nem Java.
Alapvetően nincs olyan, hogy inicializálatlan változó.
Az int i; sem inicializálatlan abban az értelemben, hogy végezhetsz vele műveleteket. Jó, hát kezdő értéke bármi lehet. De ez is inkább C örökség.

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

"T akarmi is lehet, egy valtozonev is."

A környezetből kiderül hogy mi lehet. A fordító el tudja dönteni, hogy mi kell legyen. Akkor?

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

Javaban nincs olyan, hogy egy objektum számára már lefoglaltad a memóriát, de nem inicializálod.

C++-ban ugyan van ilyen, a statikus globális változóknál, de nem hiszem, hogy azt szeretnéd ráerőletetni a stacken lévő objektumokra is. Ha nem akarsz használni egy változót, akkor ne deklaráld, máskülönben ott deklarálhatod, ahol már tudod, hogy milyen konstruktort szeretnél hívni. A nem inicializálós változatban kétséges lenne, hogy egyáltalán meghívódik-e a destruktor.

A nem inicializált változónak későbbi ponton való inicializálását sem tehetnéd meg az '=' operátorral, hiszen az már másra van használva, így az inicializált/nem inicializált változókra mást jelentene. Összességében ez egy halott ötlet, amit mondasz.

Mar miert ne tehetnem meg? C-ben miert tehetem meg? Ledefinialom egy keresociklus elott a valtozot, de az erteket csak akkor adom meg, ha megvan az erteke. Nyilvan a kereses elott meg nem fogom tudni, mit szeretnek belerakni, de ha a cikluson belul definialom, akkor meg pofaraesek a scope miatt. Tehat mindenkepp "inicializalatlanul" kell hagynom. Ehhez kepest a mostani ertelmezes szerint lefut egy komplett konstruktor, annak minden overhead-jevel egyetemben, csak azert, mert szuksegem van egy T tipusu valtozora. Minek?
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

mert a c++ már csak ilyen. nem tudod máshol deklarálni és máshol inicializálni a változót, mindenképpen lefut legalább egy üres konstruktor.

Mert egy T típusú változót definiáltál pointer helyett.

KisKresz

Miert definialjak pointert ha nincs ra szuksegem? Hogy minden if vegere beszurhassam, hogy delete x; ?
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

" Hogy minden if vegere beszurhassam, hogy delete x; ?"

Bruhaha.
Használd a try ... finally ...; blokkot.

A finally lefut return eseten is?
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Ne menj el a cselre, C++-ban nincs finally.

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

:D
(amúgy használjon MS C++-t, abban van __try és __finally)

Aztat hol tudom letolteni a Linuxomra? Ilyen tehenes Linuxot hasznalok, na, monddmar... nem jut eszembe. :-D
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

szerintem torrenten megvan, wine alatt talán el is indulna :P

Mint látható elindul :). Ide kattintva appdb bejegyzés.

WOW.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Ha iróniának szántad esetleg... Nem kioktatásnak, vagy ilyesminek írtam, csak emlékeztem az appDB bejegyzésre.
BTW én sem használtam még.

Az erdeklodot (aminek a vegen smiley volt) azt csak elcelodesnek szantam, az altalad linkelt appdb bejegyzesen pedig borzasztoan elcsodalkoztam, mert tenyleg csak hulyesegbol irtam.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Jaaaa :)
Igazából én annyira nem csodálkoztam rajta. Elvégre wine libbel linux alatt windowsos binárisokat "könnyen lehet csinálni", hát gondoltam miért ne működhetne ez fordítva is.

Aztán rájöttem, hogy egy fordító nem nagy dolog olyan szempontból, hogy azért a wine már directX-es appokat wrappol 100%-osan, ezer meg ezer függőséggel, szóval egy bináris működésre bírása már nem lehet túl nehéz. Egy forráskód parsolása, és fordítása, linkeléese pedig ehhez képest mégúgz sem tűnik nagy feladatnak.

Ha iróniának szántad esetleg... Nem kioktatásnak, vagy ilyesminek írtam, csak emlékeztem az appDB bejegyzésre.
BTW én sem használtam még.

Nem, hanem azért, hogy amikor a destruktor lefut, ne legyen inicializálatlan az objektumod. (Ezt lejjebb már írták, azt hiszem.)

KisKresz

Azért, mert ha megtehetnéd, akkor:

T x;
T y=T();

...
x=T(5); // itt inicializálsz
y=T(5); // itt operator= hívódik

ami így totálisan veszélyes technika lenne.

A felvetett problémádra pedig valószínűleg az auto_ptr-t lenne a megoldás, esetleg a shared_ptr.

A példádnál maradva, C-ben int esetében a memóriaterület lefoglalódik, viszont az int nem kap kezdeti értéket. C++ nyelvére átfogalmazva: az int default konstruktora nem állít be kezdeti értéket.

Nézzük, mi történik egy saját osztály esetében, ha nem írsz default konstruktort:
Lefoglalódik a memóriaterület, majd a fordító által generált konstruktor, ami nem csinál mást, mint meghívja az adattagok default konstruktorát.
Ha ezek a default konstruktorok nem csinálnak semmit (pl mert int-ek a tagok), akkor az osztály konstruktora sem.
Tehát pontosan az történik, amit te szeretnél.

Írhatsz-e olyan default konstruktort, ami szintén ezt csinálja (a semmit)? Igen.

Azaz mint annyiszor a C++ készítői a te kezedbe adták az irányítást.

A problémád nyilván abból adódik, hogy a legtöbb (mások által írt) osztály konstruktora nem ilyen. Ennek az az oka, hogy a valóságban sokkal kevesebbet nyersz azzal, hogy megspórolsz pár kezdeti értékadást, mint amennyit vesztesz azzal, hogy megszívathatod magad egy "inicializálatlan" osztályon hívott tagfv-nyel. (Ahol a tagfv ugye lehet a destruktor is, ami garantáltan meghívódik.)

Amit te számon kérsz a C++ tervezőin az az, hogy miért nem adnak lehetőséget arra, hogy felülbíráld az osztály készítőit, azaz szeretnéd inicializálatlanul létrehozni az objektumot, miközben az osztály készítői szerint ez rossz ötlet. (Pl. azért mert a destruktor dobna egy hátast az inicializálatlan objektumon.)
Ez kb olyan, mintha azt kérnéd számon, hogy ugyan már hadd hívj meg egy private fv-t az osztályon kívülről, csak mert neked most ahhoz van kedved.

(Halkan jegyzem meg, hogy a C++ van annyira flexibilis, hogy hackeléssel (placement new) még meg is tudod oldani amit szeretnél. Igaz ekkor a destruktort is kézzel kell meghívnod. Az azért nem elvárható, hogy még kényelmessé is tegyék neked...)

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

En meg csak memoriateruletet sem szeretnek lefoglalni. Szeretnek egy modszert, ami csinal nekem egy T tipusu x valtozot, ami majd valamikor "inicializalodik" vagyis memoriaterulet foglaltatik neki, illetve konstruktorok meg minden egyeb fut le rajta.

A gond az, hogy egy osztalynal nem csak az adattagok inicializalodnak, hanem a szuloosztalyok konstruktora is lefut (le kell fusson), fuggetlen attol, hogy az en konstruktorom ures-e vagy sem. Azt viszont mar nem en vezerlem, hogy ott mi van.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

En meg csak memoriateruletet sem szeretnek lefoglalni. Szeretnek egy modszert, ami csinal nekem egy T tipusu x valtozot ami majd valamikor "inicializalodik" vagyis memoriaterulet foglaltatik neki, illetve konstruktorok meg minden egyeb fut le rajta.

write only vagy, már javasoltam két megoldást is kettővel fentebb.

Mindket modszer szintaktikailag... nem ugyanugy nez ki, mint egy valtozodeklaralas. Persze, koszonom a tanacsot, ki fogom probalni, es valoszinuleg jo megoldas, ettol azonban meg nem kedvelem ezeket a korbedolgozasokat.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Igazából ha a szintaktikába belemegyünk, akkor pont a Java/C# nem következetes, hiszen nagyon nem ugyanaz történik, ha azt írod, hogy int i;, szemben a T x;-szel.

Java-ban az egyiknél létrejön egy int típusú változó (és emlékeim szerint automatikusan 0-ra inicializálódik), míg a másiknál csak egy referencia.

A C++-ban viszony mindkét esetben létrejön egy-egy lokális változó.
Nincs meglepetés, a felhasználó osztályai ugyanúgy viselkednek, ahogy a beépített típusok.

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

Ha találsz egyetlen nyelvet ahol ilyen van, szólj.
Mert a Java (C#, whatever) nem ilyen.

Ott ha azt írod, hogy T x;, akkor az nem "csinál neked egy T típusú x változót", hanem létrehoz egy T típusra mutató referenciát. Ez nem más mint egy mutató, ami regisztrálásra kerül a GC-ben. Ezek után a kódodban lesz egy new hívás is.
Tehát amit szeretnél arra C++-ban (is) a mutató a megoldás. (Aminek létrehozása nyilvánvaló okokból gyorsabb mint egy Java referencia létrehozása.)

Persze ekkor a delete-ről magadnak kell gondoskodnod.
Vagy használj auto_ptr-t, vagy shared_ptr-t. Vagy ha bátor vagy, használj C++-os GC-t. :)

"A gond az, hogy egy osztalynal nem csak az adattagok inicializalodnak, hanem a szuloosztalyok konstruktora is lefut (le kell fusson), fuggetlen attol, hogy az en konstruktorom ures-e vagy sem. Azt viszont mar nem en vezerlem, hogy ott mi van."
Az a konstruktor azért nem üres, mert a szülő osztály készítői szerint nem jó ötlet inicializálatlan objektumokkal bohóckodni. Ha ezt felülbírálod, az tényleg ugyanaz a kategória, mintha private tagfv-t akarnál hívni az ősosztályból.

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

Akarja a fene vezerelni, en nem. Engem egyszeruen csak zavar az, hogy letrejon egy - ures - objektum, amit a vegen ugyis el fogok dobni, mert valojaban csak a taroloja kellett, maga az objektum nem.

Most mar amugy kezdem erteni, de ettol meg nem tartom feltetlen jonak, hogy igy van - de hat mit lehet tenni? :-) Az a kar, hogy a pointereket nincs, aki eltakaritsa utanam, nem letezik "lokalis" pointer (jo, persze, lehet alloca-val buveszkedni, de az mar nagyon gany dolog c++-ban). En ugyanis alapvetoen lusta vagyok.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Az a kar, hogy a pointereket nincs, aki eltakaritsa utanam, nem letezik "lokalis" pointer

auto_ptr is your friend.

tényleg, szerintem kezdj közelebbi ismeretséget kötni a refcounting megoldásokkal, ha C++-t szeretnél komolyabban használni. pl. ha szeretnél exception-öket, és szeretnél _bármilyen_ dinamikusan allokált memóriát használni, akkor szinte "must have" valamilyen smart pointer osztály használata.

Lehet megnezem oket. Bar, mivel elsosorban a c++ cuccaim Qt-re epulnek, nem tudom, hogy mennyire fognak ezek osszejonni.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

nem ismerem a qt-t, de nagyon meglepődnék, ha semmiféle smart pointer nem lenne benne. egyszerűen nem lehet értelmesen c++-ozni nélkülük.

Akkor te ezt keresed:
http://labs.trolltech.com/blogs/2009/08/25/count-with-me-how-many-smart-pointer-classes-does-qt-have/

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

Igazából a problémád annyira nem egyedi, hogy ilyen "lokális pointer" van.
auto_ptr-nek hívják, és az STL része. Sokan nem szeretik, de az azért szokott lenni, mert másra is akarják használni. (Másra meg nem jó, mert egyszerű mint a faék. Cserébe viszont 0 overhead-je van.)

Qt-ben lényegében ugyanez a QScopedPointer.

Ha tényleg azt akarod, hogy mint a java-ban ne nagyon kelljen törődni a delete-ekkel, akkor ott a tr1::shared_ptr, vagy a boost::shared_ptr, vagy a QSharedPointer. Ezek már nincsenek ingyen, de néha hasznosak.

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

>Qt-ben lényegében ugyanez a QScopedPointer.

Ez biztos? Most nézegettem a korábban már linkelt Q*Pointer-es blogot, de annyi mindnent linkelt, amiket átfutottam, hogy mostanra feladtam. Gyorsan ki is próbáltam újra az auto_ptr-t, és első ránézésre tényleg ugyanazt tudja, mint a QScopedPointer. Viszont mi a helyzet az exceptionon, ne adj isten goto kezelésével?

Exception dobásánál (ha volt mi elkapja), az auto_ptr is megszűnt. Ha nem volt try-catch-ben, akkor meg ugye lehalt az egész program, szóval azért szűnt meg a mutató.

Ha esetleg ezzel kapcsolatban valami rendet tudnál tenni a fejemben, azt megköszönném :)

Általános szabály az, hogy a lokális változók destruktora azonnal meghívódik amint kilépsz a blokkjából. Hogy ez a kilépés normál kilépés, return, break vagy throw miatt történik az mindegy.

Az auto_ptr pedig annyit csinál, hogy a destruktorában meghívja a delete-et arra a mutatóra amit tárol. (Illetve néhány operátorát úgy definiálták, hogy úgy lehessen használni mint egy közönséges mutatót.)

A QScopedPointer alapvetően két dologban különbözik:
- nincs operator=
- meg lehet adni saját deleter fv-t. Pl egy előre definiált:
QScopedPointer<int, QScopedPointerArrayDeleter<int> > arrayPointer(new int[42]);

(Mert ugye auto_ptr-t nem lehet delete[]-tel használni.)

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

Rendben, köszönöm. Bár olvastam, hogy tudsz a template-tel saját deleter függvényt átadni a QScopedPointernek, viszont tegnap este már nem jött át, hogy ez miért is annyira nagy jóság.

És vajon az miért jó, hogy az auto_ptr-re van definiálva operator=()? A QSP-ről írták, hogy arra mivel nincs definiálva, ezért nem tudsz neki véletlenül new-val memóriát foglalni (fordítási hiba).

Ejj, nagyon nem ertesz te ehhez, es nagyon nem erted, hogy mi miert hogan.
Inkabb a C/C++ temakba ne szolj bele.

A gond az, hogy soha senki nem mondja meg, hogy valojaban mi ertelme van neki, miert jo ez, mindenki csak azt mondja, hogy "hat, ez c++-ban igy van, mert c++-ban ezt igy kell csinalni, mert a c++ nem java". Es mindenki azt gondolja, hogy ez igy frankon, jol meg van magyarazva. Most ketto eset lehetseges: vagy senki nem tudja valojaban, vagy soha senki fel nem tette ezeket a kerdeseket.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

mit segít rajtad a kérdés feltevése? így csinálták meg, ha nem tetszik, nem tudsz ellene mit tenni.

Azert, mert nem tudok ellene mit tenni, attol meg erdekelhet, hogy miert van igy, nem? Vagy tilos kerdezni?
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

nem tilos kérdezni, megkeresheted a c++ szabványosító bizottság üléseiről szóló jegyzőkönyveket, szerintem simán fent lesz a neten, ha nagyon akarod, még akár a résztvevőket is megtámadhatod emailben.

de azt ne várd, hogy egy szabványhoz kötelező jelleggel készítsenek egy magyarázatot, hogy miért is ezt foglalták szabványba.

A vicces az, hogy még a magyarázat is létezik.
Rengeteg dolog benne van a Stroustrup C++ könyvében, illetve írt egy könyvet ami elvileg csak erről szól: "The Design and Evolution of C++".

Kezdetben nekem is csomó dolog volt, ami nem tűnt logikusnak, de sorban mindről kiderült, hogy okkal van úgy.
Az okok a következők szoktak lenni:
- ahogy én gondoltam az lehetetlen, vagy nem hatékony, vagy VM kéne hozzá
- a C kompatibilitás közbeszól
- simán hülyeség, vagy csak többet ártana mint használna

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

Igen, talan reszben az lesz az egyik valasz, hogy VM (pontosabban GC) kellene ahhoz, hogy kenyelmesebb legyen ez a resze, reszben pedig az, hogy a konstruktor/destruktor hivasok logikaja egy picit (oke, sokkal) masabb, mint mas nyelvekben (C#/Java). Vegulis jo, mert legalabb ezt is megertettem. Koszonom a valaszokat.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Nyílván ezért szopunk egy csomó hülyeséggel, nem pedig azért, mert a C++ comittee tagja a földről elrugaszkodott barmok, akik gyakorlati projectet utoljára akkor láttak, amikor felfedezték Amerikát. A vikingek.

Soroljam a kényelmetlen szintaxisokat, fölösleges szintaktikai megkötéseket? Az exception rendszer hiányosságait? Az stl kényes, lassú, elavult voltát? A hiányzó szabványos könyvtárak okozta fejlesztési nehézségeket? Hogy minden cégnek a fejlesztés megkezdése előtt gyakolratilag meg kell írnia a c++ hiányzó részeit, ha a Qt nem jöhet szóba?
Azt a sok szintaxis okozta szívást, amivel nap mint nap szembesülünk a fejlesztésnél?

Senki nem magyarázza meg nekem, hogy pl. az, hogy template-ből leszármazva nem tudom használni a protected tagokat csak usingolás után, értelmes. Hehe.

Olyan a C++, mint a demokrácia. Tudjuk, hogy szar, de nincs jelenleg jobb (bizonyos célokra).

Erre a template-es protectedre írj már példát plz..

Ah, erről mintha lenne a c++ faq-ban, a lényeg,
hogy 'this->a'-t kell írni.

szerk:
igen, itt van: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.19

Jaja, az a masik megoldas a using hasznalata mellett.

De milyen gaz mar ez, nem? Na, az ilyen hulyesegek miatt kell 10-15 ev az ember eletebol, hogy expert legyen C++-bol...

Pont ez a szép benne, hogy olyan dolgok vannak benne, amikről csak a c++ mágusok suttognak sötét folyosókon egymás közt:)

Harry Potter fan ? :-)

Nem, egyszer egy levlistán olvastam a placement new kapcsán:)

Fentebb már kifejtetted, hogy véleményed szerint ez azért van így, mert a C++ tervezői inkompetens barmok. Nyilván, mert eszükbe sem jutott ez az egész dolog.

Ezzel szemben a szabvány 14.6.2-es pontjában le van írva lényegében az a példa amit te is leírtál, és explicite le van írva a következő:
"In the definition of a class template or a member of a class template, if a base class of the class template depends on a
template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition
of the class template or member or during an instantiation of the class template or member."
Azt tehát kizárhatjuk, hogy nem jutott eszükbe. Mivel ez pont egy eltérés attól ahogy normál esetben a name lookup működik, azt is kizárhatjuk, hogy tökmindegy alapon választották ezt. Akkor vajon mégis miért van ez így?

Én két esetet látok:
- direkt szívatni akarták a programozókat
- van valami komoly oka, ami számodra/számomra nem nyilvánvaló

Én a másodikra szavazok. Az ok engem is érdekelne, de sajnos nekem nincs meg a "The Annotated C++ Refernce Manual" könyv, illetve Stroustrup is megharagudott rám, mert nem fizettem a 2. sörét. Szerinte neki kettő jár, mert a C++ könyv 2 kötetes, szerintem meg csak egy könyv. Na mindegy.

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

Igen, a 2. ok lehet az igazság.

Először azt sem értettem miért kell azt írni template osztályban, hogy

typename MyType::iterator my_iterator_;

De megvilágosodtam, most már tudom; biztos ennek is van valami oka.

Ettől még zavar. :)))

"Nyílván ezért szopunk egy csomó hülyeséggel, nem pedig azért, mert a C++ comittee tagja a földről elrugaszkodott barmok, akik gyakorlati projectet utoljára akkor láttak, amikor felfedezték Amerikát. A vikingek."

Nyilván fogalmad nincs kik a comittee tagjai, illetve, hogy mennyire összetett dolog egy nyelv tervezése. Plusz elfelejted, hogy mikori az utolsó C++ szabvány, és azóta mennyi víz lefolyt a Dunán.

Van pár kényelmetlenség, igen. (Mondjuk párat megoldanak C++0x-ben.)
De ha csak nem vagy boost fejlesztő, ezek igen ritkán kerülnek eléd.

Az exception rendszer hiányosságairól beszélhetnél, nem tudom mire gondolsz.
Az sem világos, hogy az STL miért kényes és elavult. Miért lassú? (Általános dolgokat tekintve, speciális esetben mindent lehet optimalizálni.) Azt aláírom, hogy nem mindig kényelmes.

És igen, az valóban hátrány néha, hogy a szabvány könyvtár nem tartalmaz sok mindent. De tekintve, hogy most, 2010-ben is van olyan fordító (lásd a fentebb linkelt Qt blogbejegyzés végét), ami nem volt képes sem a C++ szabvány, sem a lib maradéktalan implementálására (ez egyébként még az MS-nek is csak a közelmúltban sikerült), akkor azt hiszem én örülök, hogy csak ennyit tartalmaz.

Egyébként meg ott a Qt, a boost, és még sorolhatnám. Rengeteg ilyen-olyan lib közül választhatsz, mindnek más a gyengéje és az erőssége.
Ha pl csak egy adatbázis kezelő lib lenne, akkor azon menne a sírás, hogy az nem jó mindenkinek. (Lásd STL. Pont ez történik.)

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

Ha valahol sokan sirnak, ott gond van. Akarkik a tisztelt committee tagjai, akkor is. Meg ha maga az atyauristen veste volna kobe a szabvanyt, akkor is. Meg ha minden egyes pontjara letezik logikus es konisztens magyarazat, akkor is. Marpedig valoban meglehetosen nyugos c++-ban fejleszteni egy projektet; mondom ezt annak ellenere hogy nyilvan kordaban tarthato es kapsz is cserebe valamit a sok szivasert. De az erzet, na az valoban kokorszaki.

"Meg ha minden egyes pontjara letezik logikus es konisztens magyarazat, akkor is."

Azért ez a "jobb nincs" kategória, azért meg kár sírni...

"Marpedig valoban meglehetosen nyugos c++-ban fejleszteni egy projektet"
Miben nem? Nekem nem tűnik úgy, hogy valaki már megtalálta volna a szent Grált.
Törvényszerű, hogy egy bonyolultsági szint után szívsz. Nyilván nem mindegy hogy mivel mennyit. Itt vannak eltérések a nyelvek között, de mindent összevetve én C++-szal eddig kevesebbet szívtam mint mással.
(Sőt újabban én csak MSVC-vel szívok mint a torkosborz, gcc teljesen problémamentes.)

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

Kicsit durva voltam, igen. Nyílván a comittee tanácstagok nálam okosabbak és tapasztaltabbak, tekintve hogy még nem vagyok 30 se, tehát a C++ idősebb, mint én.

Fejlesztettél már nem mainstream fordítóval? Pl. Analog Devices Visual Dsp szutyok?
A boost le sem fordul (illetve fordítési hibát ad template-ek esetén.)

Qt-ről ne is álmodjunk.

Tudom, hogy milyen összetett egy nyelv fejlesztése. Sajnos a C++-szal koncepcionális problémák vannak.

A legnagyobb probléma, hogy nincs jobb compiled nyelv nála. A C túlságosan fapados, a többi meg nem elterjedt, vagy hiányoznak belőlük dolgok.

Hogy az STL miért kényes és elavult: írjál egyszer egy allocatort: látni fogod, hogy az stl-t akkor fejlesztették, amikor nem lehetett egyszerre több memóriát lefoglalni, mint 64k. Hasonlítsd össze mondjuk a Qt-s string-et az stl-essel: az stl-ből alapvető feature-ök hiányoznak pl. stringkezelés terén: sprintf és alternatívái, unicode. Nincs stringstream.

Memóriafoglalás megfelelő managelésére nem gondoltak: vector memóriát nem lehet csak trükkel felszabadítani, deque-ban a que-k méretét nem tudod megadni.

Mértünk annó msvc alatt vector és natív tömb közti különbséget bejáráskor. Megdöbbentően lassú a vector. Az első list kiváltására írt próbálkozásom 10%-al gyorsabb volt, mint az ms stl-lel adott list, az stl algoritmusaira.

Sokat kell gépelni: ilyesmiket, hogy
for ( MyList::const_reverse_iterator i = lst.rbegin(); i != lst.rend(); ++i )
A reverse_iterator-iterator konverzió egy rémálom. Egyszer már dumáltunk itt erről.

Az stl algoritmusok viszont jók.

Exception-ök hiányosságai: finally hiánya. C++00x-ben tudtommal nem raknak bele ilyesmit. Mondjuk én egy az egybe le tudnék mondani az exception-ökről. :)

Nincs normális switch alternatíva: a C-és switch a break-kkel, default-tal elavult, a PDP-11 sajátosságait hordozza. Kötelező leírnod, hogy break, holott pont fordítva lenne logikus, mivel ritkább eset, hogy nem írunk break-et, mint fordítva.

A már írt template-es paráim (template-ből származás esetén nem ismeri fel a szabvány a protected membereket). A template további kényelmetlenségei, undorító leírni egy fv nevét, ha utólag írod le a törzsét, nem az osztálydeklarációban.

Nem nőttük ki a C-és include-rendszert, minden header-t újrafordítunk minden cpp file fordításakor. Rémálom, megnehezíti a hibakeresést és lelassítja a fordítási időt, ugyanakkor nem hiszek benne, hogy túl sok optimalizációs lehetőséget rejt magában.

Egyáltalán: a fordító nem ismeri a project-et, mint olyat. Egy új fejlesztés esetén kezdhetjük megírni a saját build rendszerünket, cmake, autoconf meg hasonló nyelveken, vagy kicsit sem tudunk hordozható projectet készíteni. Kis túlzással, persze. Ezzel az állításommal kevesen értenek egyet.

---

Mégiscsak kemény, hogy minden héten, minden második héten találkozok egy új nyelvi elemmel, nyelvi problámával, amiről még nem hallottam, mert még sosem jött elő. A Jóisten tudja hány év fejlesztés után. Nem, nem szoktam C++ Faq-okat böngészni, csak ha rákényszerülök. Nem vagyok C++ fetisiszta: programokat szeretek írni, nem annak a fényében tetszelegni, hogy ez mennyire szép/csúnya C++-ban, de sajnos rákényszerülök. Sajnos a C++ szabvány nem nyílvános, ezért másodlagos forrásokra szorulunk.

Ha egyszerre három fordítóval dolgozol, az rámutat a nyelv hiányosságaira... :)))

"Hogy az STL miért kényes és elavult: írjál egyszer egy allocatort: látni fogod, hogy az stl-t akkor fejlesztették, amikor nem lehetett egyszerre több memóriát lefoglalni, mint 64k."
Ez tuti, hogy nem igaz, már csak azért sem, mert ilyen megkötés leginkább a 16 bites x86 rendszerekre volt jellemző. Ettől még lehet az allocator mint olyan fapados, de:
- Más nyelven konkrétan nincs lehetőséged allocator-t írni.
- Az ember jó esetben nem ír állandóan allocator-okat.

"Hasonlítsd össze mondjuk a Qt-s string-et az stl-essel: az stl-ből alapvető feature-ök hiányoznak pl. stringkezelés terén: sprintf és alternatívái, unicode. Nincs stringstream."
Azt én is írtam, hogy néha nem kényelmes.
unicode mondjuk azért van (wsprintf), bár a konverziók tényleg macerásabbak.
printf helyett a << operátort találták ki, lehet nem szeretni, de ettől még ez van.
String stream mondjuk pont van.

"Memóriafoglalás megfelelő managelésére nem gondoltak: vector memóriát nem lehet csak trükkel felszabadítani, deque-ban a que-k méretét nem tudod megadni."
Ez mondjuk igaz.

"Mértünk annó msvc alatt vector és natív tömb közti különbséget bejáráskor. Megdöbbentően lassú a vector."
Ez biztos, hogy msvc sajátosság (volt). Pl.: gcc-nél a vector iterátor lényegében egy mutató, az inline-ok miatt nincs semmilyen overhead.

"Sokat kell gépelni: ilyesmiket, hogy
for ( MyList::const_reverse_iterator i = lst.rbegin(); i != lst.rend(); ++i )"
Ez tény. C++0x-ben ezért lesz auto.

"A reverse_iterator-iterator konverzió egy rémálom. Egyszer már dumáltunk itt erről."
Igen, volt erről itt vita, de konszenzus nem, sokan nem is értettük a problémátokat, nekünk egyértelműnek tűnik...

"Exception-ök hiányosságai: finally hiánya."
A finally sokszor felmerült, C++0x kapcsán is, de mindig elvetik, ugyanis C++-ban nincs rá szükség. Bővebben

"Nincs normális switch alternatíva: a C-és switch a break-kkel, default-tal elavult"
C kompatibilitás miatt nagy változás itt nem lehet. Marad az if, else-if szerkezet...

"Nem nőttük ki a C-és include-rendszert, minden header-t újrafordítunk minden cpp file fordításakor."
Nem is fogjuk. Egy két szabályt betartva egyébként ez nem hatalmas probléma.
Csak meg kell szokni, hogy ne include-olj be fűt-fát, mindig csak azt amit kell, és csak akkor ha kell. (Pl.: a .h fájlban ha nincs T típusú adattagod, csak mutatód meg referenciád (esetleg visszatérési értéked), akkor nem kell include.)
Csodákat lehet művelni.
Illetve ott a precompiled header. Kicsit hack szagú, de működik...

"Egyáltalán: a fordító nem ismeri a project-et, mint olyat."
Ez speciel nekem nem hiányzik. Sőt általában utálom az olyan IDE-t ami saját project fájlokat használ.

"Mégiscsak kemény, hogy minden héten, minden második héten találkozok egy új nyelvi elemmel, nyelvi problámával, amiről még nem hallottam, mert még sosem jött elő."
Ez tény. A nyelv bonyolult. Talán a legnehezebb. Szerintem egyébként megéri, én beleszerettem néhány dologba ami máshol egyáltalán nincs. (template, operator overloadnig, stb.)
Stroustrup egyik célja volt egyébként a C++0x kapcsán, hogy egyszerűbbé kell tenni az alapok elsajátíthatóságát. Kérdés, hogy ezt a célt el tudták-e érni, illetve egy ilyen sokszínű nyelv esetén egyáltalán elérhető-e...

"Ha egyszerre három fordítóval dolgozol, az rámutat a nyelv hiányosságaira... :)))"
Az inkább a fordítók hiányosságaira. :)

Nem gondolom, hogy a C++ tökéletes. Sőt kifejezetten vágyom a C++0x néhány szolgáltatására. De azt sem bírom, amikor olyanok szidják, akik nem is ismerik.

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

"Fejlesztettél már nem mainstream fordítóval? Pl. Analog Devices Visual Dsp szutyok?"

Nem hálistennek, de ezt azért nem vetném a C++ szemére. Az igaz, hogy bonyolult, és a fordító készítők szeretnének kihagyni belőle dolgokat, de a tény, hogy utána ezek a hiányosságok téged zavarnak csak azt mutatja, hogy ezek fontos dolgok.

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

Az, hogy megkérdezed, az magában nem gond, viszont előtte igazán belegondolhatnál te magad is, hogy a dolgok miért vannak úgy, ahogy, és miért nem úgy, mint máshol. De az igazi probléma az az, hogy úgy teszel, mintha nem is érdekelne a miért, hanem felteszed, hogy neked van igazad.

+1

A C/C++ filozófia ilyen.
Mi nem tetszik?
Ha az nem tetszik, hogy nem érted, és halvány lila gőzöd sincs róla, hogy mit, miért, hogyan, akkor olvass el pár ezer oldal C++ könyvet, meg írj pár ezer sort.
Ezt nem lehet kifejteni egy-egy hozzászólásba.

10 éve programozom benne. Aztán még a tavalyi kódjaimat is másképp csinálnám ma már. :)
--
http://www.naszta.hu

Jaja :)))

Ez megnyugtató, ahhoz képest, hogy lassan három évet lehúztam C++ világban, ezek a topikok úgy be tudnak vezetni az erdőbe mint az állat. Irulok-pirulok néha itt a monitor előtt, de igyekszem mindent felfogni, heves fejvakarások közepette :)

+1

Nekem 7-8 év, iparban 6+, és ez rám is igaz.

"Most ketto eset lehetseges:
...
vagy soha senki fel nem tette ezeket a kerdeseket."

Ugye nem hiszed magad akkora pengének, hogy te olyan kérdést teszel fel, amit még soha senki a több millió emberből, aki használja a C/C++ nyelveket?

A "ketto eset lehetseges" sem jo megközelítés, mondhatni hülyeség.
Mert az is lehet, hogy senkinek nincs kedve több oldalas esszét írni neked a C filozofiáról, hogy aztán kétszer ennyit írjon a C++ filozófiáról is, hogy megértsd.
A C++ -ba így passzol bele, ahogy van, ha nem érted, akkor járj utánna, tanuld meg, tapasztald ki, fogd fel, de semmiképp se mondj hülyeségeket.

Én fent még próbálkozom, de egyébként:
+1

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

+1

+1

miota elkezdett egy kicsit javazni nagyon kinyilt a csipaja, es mindenhez okoskodik :(

Semmi gond nincs azzal ha valaki hulyeseget beszel es azzal sem, ha mondjuk negyedjere latja at igazan mirol van szo, de addig kitart az eredeti elgondolasa mellett. Nem kene allandoan viselkedesi utmutatot tartani. Inkabb elmagyarazni probald :P

Dinamikusan hozz létre objektumokat, így:
T obj = new T;

Ez hogy jon ide? Valahol dinamikusan kell, valahol nem.

----------------------
while (!sleep) sheep++;

Nem mindig kell dinamikusnak lennie. Es egyebkent, a deklaraciod rossz, az obj az egy T* nem pedig egy T. Es ezen van meg egy kotelezo delete overhead is.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Akkor már inkább ide szoktassuk őket:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.2

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

Azt is kérdezd meg, hogy mi a különbség e kettő között:

T* t0 = new T;
T* t1 = new T();

:))))

És azt is, hogy hogyan lehet mégis elérni, hogy a kettő ne különbözzön! ;)


class T
{
public:
T & operator () ( void )
{
return T;
};
};

vagy valami ilyesmi... :)
--
http://www.naszta.hu

Semmi esetre sem.

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

Megmondom őszintén, hogy eddig nem használtam olyan könyvtárat, ahol volt jelentősége. Köszi a cikket, már értem mit néztem be.
--
http://www.naszta.hu

Nem, a kutya a zero-initialization-ban van elásva.
Vagyis ha van egy olyan (globális) new operátorod, ami 0-ra inicializálja a foglalt memóriaterületet, akkor az első változat is effektíve zero-inicializált lesz, így podtype-okra és nem podtype-okra is meg fog egyezni a foglalt memóriadarabok értéke.

Mindazonáltal ilyet nem szabad csinálni, csak érdekességképpen vetettem fel:)

Ha valakit tényleg érdekelne:
stackoverflow.com

Jótanács:
Ne használd a zárójeleket, és ne írj olyan kódot, ahol ez számít.

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

Mondjuk én kerülöm az operator ()-t, bár biztos van ahol nélkülözhetetlen...
--
http://www.naszta.hu

Ez itt nem operator().

Néha nagyon hasznos pedig. (Most nekem az jutott eszembe, ahol numerikus problémák megoldása során matematikailag egy függvényt kellene átadnod egy eljárásnak - mondjuk egy gyökkeresőnek - de a függvény kiértékeléséhez paraméterek is kellenek. Így működik pl. a Numerical Recipes új változata, és szerintem sokszor nagyon praktikus, és a kód közepe olvasható marad, nem úgy, mintha valamilyenosztaly.kiertekel(x)-eket kellene írni mindenütt.)

(Funktornak hívják)

STL is hasznalja, lásd pl. find_if és társai. A kód karbantartását persze megnehezíti, 'kiertekel'-t könnyebb megtalálni és lecserélni.

"kmARC" már rögtön az elején megadta a választ.
A lényeg, hogyha van az osztálynak alapértelmezett konstruktora (akár a fordító hozta létre, akár te), akkor az első verzió a helyes.

Tehát ez:

T peldany;

A másodikat pedig egy függvénydeklarációnak veszi a fordító. És csak akkor fog jelezni, ha a peldany-t, mint az osztály egy példánya szeretnéd használni.

Itt van egy komplett példa:

class T {
public:
    int x;
};

int main(int argc, char** argv) {
    T p1;
    T p2();
    
    p1.x = 2;
    p2.x = 2;
}

Ha a p2.x =2; sort kiveszed, helyesen lefordul a program, mivel nem akarunk a p2-vel osztály objektumként bánni. Ha benne hagyod, akkor jön a hiba:

Idézet:
error: request for member ‘x’ in ‘p2’, which is of non-class type ‘T ()()’

Kiabál a fordító, hogy nem osztály típus a p2!