Article View: de.comp.lang.c++
Article #1597Re: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen
From: Dietmar Kuehl
Date: Thu, 22 Feb 1996 02:28
Date: Thu, 22 Feb 1996 02:28
271 lines
15389 bytes
15389 bytes
Hi,
Ullrich von Bassewitz (uz@wuschel.ibb.schwaben.com) wrote:
: Wenn ich mal neugierig fragen darf: Was tust Du
: ueberhaupt fuer C++? Ich gebe ehrlich zu, dass ich keine Ahnung habe.
Ich vermute, dass Harald Fuchs mit meinem Engagement fuer C++ meinte,
dass ich einer von sieben Moderatoren von comp.lang.c++.moderated bin
(Robert Martin, James Kanze, Dominique De Vitto, David Vandevoorde,
Herb Sutter und Howard Harkness sind die anderen). Ich wollte schon
letztens erwaehnen, dass ich mir diese Arbeit "aufgehalst" habe, um die
Qualitaet in clc++ zu verbessern, was uns, soweit ich das beurteilen
kann, auch gelungen ist. Ein aehnliches Engagement waere hier
eigentlich auch angesagt (aber nicht von mir: eine Newsgroup reicht).
Allerdings weiss ich nicht, ob es sich wirklich lohnen wuerde. Wir
haben jetzt in clc++m etwa ein fuenftel soviele Artikel wie clc++ hatte
bevor es moderiert wurde. Das wuerde hier auf 2-3 Artikel pro Tag
hinauslaufen.
Vielleicht ist das nicht die beste Gelegenheit, aber da wir schon bei
der Sache sind: IMHO lohnt es sich in clc++m reinzugucken. Vieles, was
hier geposted wird, wuerde dort abgelehnt werden: Environment
Specifics, Off-Topics, FAQs, Flames... Dafuer gibt es Antworten (oft
sehr schnell, da wir uns mit dem moderieren ziemlich beeilen) zu fast
allen Fragen, die geposted werden.
: Trotzdem denke ich immer noch, dass Deine "Stilhinweise" falsch sind. Sie
: moegen in einer bestimmten Umgebung richtig sein, aber eben nur dort.
Die meisten der Stilhinweise, die ich abgebe, stammen nicht nur von
mir. Sie sind allerdings womoeglich in der Tat auf eine bestimmte
Umgebung abgestimmt: Programmeteile, die sich kein Resourceleak leisten
koennen und die ueber laengere Zeit verwendet werden sollen. Darunter
fallen z.B. alle Libraries (ich programmiere seit Jahren "nur"
Libraries, keine vollstaendigen Programme von Testprogrammen
abgesehen). Ein guter Teil der Diskussionen in clc++m und comp.std.c++
geht genau darum. ... und Klassen sind, IMHO, "Units of Reuse". Also
haben sie ein "anstaendiges" Interface zu haben. Ob ich derzeit
Exceptions benutze oder nicht, ist dabei vollkommen irrelevant: Da
davon auszugehen ist, dass genau der selbe Code auch noch in ein paar
Jahren verwendet wird, bin ich gut beraten, ihn jetzt schon darauf
vorzubereiten, mit Exceptions zu arbeiten (auch wenn der Code noch
geaendert wird: entweder wird er vollstaendig weggeworfen oder nur
unwesentlich geaendert; ersteres ist je nach Umfang und allgemeiner
Qualitaet eher unwahrscheinlich).
: > Als allererstes sei auf die potentiellen Speicherloecher hingewiesen.
: [...]
: char* verursachen dabei nicht mehr Probleme als dynamische Objekte, vor
: allem deshalb, weil char* nicht unbedingt dynamischen Speicher impliziert.
: D.h. das Problem ist kein spezifisches Problem von Zeigern auf chars und
: damit auch *kein* Grund zur Kritik an diesen.
Gerade vorhin habe ich Scott Meyers' "More Effective C++" erhalten.
Hier ein kurzes Zitat (Item 9, "Use destructors to prevent resource
leaks", erster Satz): "Say good-bye to pointers. ...". Diese Aussage
wird zwar noch etwas relativiert, zielt aber in die Richtung dessen,
was mich gestoert hat: Pointers, egal welcher Art, sind
Implementationsdetails, die in eine Klasse gehoeren. Das betrifft nicht
nur 'char*', sondern ALLE Pointer. Das Resourceleak-Problem kommt
zusaetzlich hinzu...
: Ausserdem steht es jedem frei Exceptions zu verwenden oder nicht (derzeit
: duerfte die Mehrzahl der Programmierer exceptions nicht oder nicht
: regelmaessig verwenden, schon alleine wegen der mangelnden Verfuegbarkeit).
Ich empfehle (ohne es persoenlich zu meinen), das dann 'new(nothrow)
....' anstelle von 'new ....' verwendet wird: 'operator new(size_t)'
darf nach ISO C++ Standard (coming soon to you...) Exceptions werfen:
Dies duerfte die mit Abstand prominenteste Stelle sein, wo sich mit dem
Standard die Regel unangenehm zu den Regeln im ARM aendern (die
Geschichte mit dem 'for-scope' ist dagegen nur laestig). Ab wann
Compiler damit tatsaechlich anfangen (und wann das tatsaechlich ein
Problem ist; um Code mit derartigen Problemen zu testen muss ich immer
mein Resourcelimit drastisch runtersetzen: bei > 100MB virtuellem
Speicher klappt Speicher anlegen eigentlich immer), ist ziemlich
unbestimmt.
Vielleicht sollte ich in der Tat davon absehen, meine grundsaetzliche
Paranoia gegenueber allem Code, der sich in extrem Faellen womoeglich
daneben benimmt, zu verbreiten. Persoenlich habe ich jedoch nach wie
vor ein ungutes Gefuehl bei jedem Pointer, den ich ausserhalb einer
Klasse sehe (die Diskussionen um 'auto_ptr' sensibilisieren halt doch
etwas...). Ich werde versuchen, mich in Zukunft auf "Meine persoenliche
Abneigung gegen Pointer ausserhalb von Klassen ist ja ausreichend
bekannt..." zu beschraenken.
: Und was ist mit "unsigned Counter"? Laut Deiner Argumentation ist das dann
: ploetzlich auch nicht mehr zulaessig, weil "unsigned" eine Repraesentation
: ist ("Counter" waere die Abstraktion).
Erscheint dir das als so abwegig? Siehe etwa 'size_t' (normalerweise
ein typedef fuer 'unsigned long int'). Zugegebenermassen verwende ich
oft 'int' direkt, aber nur dann, wenn ich mir ziemlich sicher bin, dass
'int' adaequat ist. Ansonsten kommt man mit einem 'typedef' besser
aus: Man kann es z.B. an einer Stelle aendern, anstelle das man es
ueberall aendert, wo es auftritt. Es mag uebertrieben klingen, aber:
Ja, ich halte 'Counter counter' fuer vernuenftig. Wenn man mit
Templates arbeitet, bleibt einem oft eh nicht viel anderes uebrig...
[Ich wollte gerade erwaehnen, dass es irgendwelche Gruende gibt, 'int'
anstatt 'unsigned int' zu verwenden, aber ich finde die Referenz nicht
(schade). Wenn unbedingtes Interesse besteht, suche ich aber spezifisch
dannach...]
: Dieses Argument halte ich fuer noch schwaecher als das erste (das man
: zumindest in einem bestimmten Bereich als zutreffend bezeichnen konnte).
Es erscheint mir eher eine Geschmacksfrage zu sein... Ich halte es fuer
ausreichend schlagkraeftig. Insbesondere, da ich schon in Programmen
nach den Abstraktionen gesucht habe. Und: Mir hilft es selbst, wenn ich
mir die Abstraktionen selbst klar mache und sie, anhand des Typs, auch
konsistent verwende.
: * Performance (class string ist um *Klassen* langsamer als eine Uebergabe
: eines Parameters als char*).
Die anderen Gruende moegen ihr Berechtigung haben (ich stehe halt
darauf alle Pointer einzupacken...). Das interessiert mich aber: Hast
Du dazu Messungen. Ist ein 'string const &' bzw. ggf. ein 'string &'
WIRKLICH langsamer als ein 'char*'? Auf welchen Compilern/Platformen?
Stepanov hat einen Benchmark fuer die "Kosten von Abstraktion" gebaut,
bei dem z.B. g++ auf SUNs recht gut abschneidet. Was mich interessiert,
ist ob die Abstraktion 'string' wirklich "teuer" (*Klassen* langsamer)
ist. Wenn Du einen Performance-Tests dafuer hast, lasse ich ihn gerne
auf den mir zugaenglichen Platformen (diverse UNIX Derivate meist mit
g++; teilweise aber auch kommerzielle Compiler) laufen.
: Wie Du wahrscheinlich auch weisst residieren die Namen fuer Typen und die
: von Variablen in unterschiedlichen Namespaces (die Low-Level Erklaerung ist:
: Der Compiler hat unterschiedliche Symboltabellen fuer die Namen von Typen
: und Variablen. Das ist wegen der C Kompatibilitaet notwendig).
: D.h. entgegen Deiner Behauptung gibt es keinerlei(!) Konflikte wenn Typnamen
: als Variablennamen verwendet werden (vorausgesetzt natuerlich, man braucht
: nicht den Namen des Typs zusaetzlich zu dem der Variablen, wovon hier nicht
: auszugehen ist).
Hm. Mir scheint, ich bin mal wieder 100% im Off... So ein
Anfaengerpatzer. Aber in der Tat: Typnamen kollidieren nicht mit den
Namen anderer Objekte (kommt daher die Notwendigkeit fuer 'typename' in
Templates: Um zwischen zwei gleichen Namen, einem Typnamen und einem Objektname,
unterscheiden zu koennen? Koennte glatt sein...).
: Ich habe das auch nicht als Kritik an Dir gemeint, sondern als Kritik an
: Harald Fuchs. Trotzdem sind Hinweise zum Programmierstil praktisch *immer*
: eine persoenliche Sache, ganz einfach deshalb, weil Programmierstil eine
: persoenliche Sache ist. D.h. bei solchen Hinweisen gehst Du immer das Risiko
: ein, dass es jemand persoenlich nimmt. Und, wie ich oben ausgefuehrt habe
: halten Deine Sachargumente lange nicht das, was sie versprechen.
Ich werde mir mehr Muehe geben...
: Nimms nicht zu hart, auch das war nicht als Kritik an Dir gedacht :-)
Oh, mein Ego laesst sich mit sowas eh nicht so leicht ankratzen. Ich
habe aus der bisherigen Diskussion gelernt ('nen bischen C++, 'nen
bischen, wie ich mich verhalten sollte). Insofern war die Kritik
konstruktiv und gegen die habe ich garnichts :-)
: > C++ wie C zu benutzen bringt keinen Vorteil.
: Auch hier: Widerspruch! Schon alleine die strengere Typpruefung, typesafe
: Linkage usw. machen viele Vorteile von C++ gegenueber C aus, auch dann, wenn
: ich keine einzige Klasse verwende, sondern weiterhin prozedural
: programmiere. Natuerlich kann ich nur einen Bruchteil der Vorteile von C++
: nutzen, aber die Aussage, so wie Du sie hinstellst ist auf jeden Fall
: falsch.
Stimmt. Ich empfehle den Leuten, die unbedingt C vor C++ lernen wollen
eigentlich auch immer, dass sie wenigstens einen C++ Compiler nehmen
sollen. Also: C++ wie C zu benutzen bringt nur geringen Vorteil.
: Soweit ok, nur musst Du dann auch damit rechnen, dass Kritik an Dir bzw.
: Deinen Argumenten kommt. Bisher, muss ich ehrlich sagen, waren letztere fuer
: mich nicht sehr ueberzeugend - aber vielleicht kommt ja noch mehr :-)
Kritik stoert mich eigentlichlich nicht... Was meine Argumente anbelangt, stimme
ich Dir zu, dass sie nicht weltbewegend sind :-( In meinem Kopf spukt halt eine
grundsaetzliche "Pointer ausserhalb von Klassen"-Phobie: Um jeden Pointer laesst
sich eine Klasse packen, die
- den Pointer initializiert (naja, ist auch nicht weltbewegend, aber
ich bin halt leicht vergesslich...)
- aussagt, was der Pointer repraesentiert (das siehst Du leider nicht als Grund)
- die mit dem Pointer assoziierten Resourcen bei Bedarf freigibt,
transferiert, dupliziert,... (ist in der Tat nur wirklich wichtig,
wenn Exceptions in der Gegend rumfliegen).
Solche Klassen, als Template inline implementiert, kosten entweder
nichts oder sehr wenig. Speziell bei Strings hat die Abstraktion
'string' noch die Vorteile, dass die Objekte leichter modifizierbar
werden, sich leichter vergleichen lassen und einige Operationen
potentiell schneller sind. In Zukunft kommen auch noch einige
Konversionen hinzu (z.B. 'string' <-> 'vector<char>'), die
Template-Members verwenden.
: > Im uebrigen interessiert mich eigentlich viel mehr, welche Gruende es
: > fuer eine Deklaration wie 'char *string' geben koennte. Vielleicht kann
: > mich irgendjemand darueber aufklaeren. Allerdings sollte damit
: > gerechnet werden, dass ich womoeglich eine Follow-Up poste, in dem ich
: > die angefuehrten Argumente versuche zu entkraeften...
: Gruende habe ich oben genug aufgefuehrt, ich warte jetzt mal auf Deinen
: Followup :-)
Hier die Gruende:
: * Low-Level Code
Egal auf welchem Level programmiert wird: Eine Abstraktion inklusive
passendem Schutz macht sehr schnell Sinn. Es ist richtig, dass 'string'
da oft nicht hilft, aber es war ja nach einem Sinn fuer 'char *string'
gefragt: Es soll ein String repraesentiert werden. Da ist nichts so
Low-Level dran.
: * Interface mit anderen Sprachen (C z.B.)
Vielleicht. Andreas sprach z.B. von 'getenv()' (in einem Follow-Up).
Allerdings kann man sowas auch gleich in einem 'string' verschwinden
lassen und mit 'string::data()' wieder zum Vorschein kommen lassen.
: * Performance (class string ist um *Klassen* langsamer als eine Uebergabe
: eines Parameters als char*).
Es hat niemand gesagt, dass der 'string' per value uebergeben werden
soll: Dafuer gibt es Referenzen. Falls die Uebergabe per Referenz
wirklich langsamer ist (ich habe keinen Test gemacht) koennte dieses
Argument ziehen. Allerdings nur dann, wenn reichlich von den Objekten
konstruiert werden sollen...
: * Bestimmte Repraesentation notwendig (z.B. Zeiger auf Shared Memory,
: Objekte im Shared Memory gehen naemlich nicht bzw. nicht portabel).
Da sich der ISO C++ Standard nicht ueber Shared Memory auslaesst, ist
ALLES unportable. ... und ich lege Dir trotzdem problemlos bestimmte
Objekte in Shared Memory an (placement-new laesst gruessen). Ausserdem
gibt es keinen Grund nicht eine Klasse zu bauen, die die Zugriffe auf
das Shared Memory Objekt einkapselt und durch einen 'char*'
repraesentiert wird (i.e. "class ShmObj { private: char *shm_mem; ...};"):
Wenn das eh unportable ist, dann kann man den unportablen Code
wenigstens in einem Punkt konzentrieren.
Wenn ich mir das so angucke, dann finde ich, dass meine Argumente fuer
mich ausreichen, Pointer aller Art nicht frei rumfliegen zu lassen:
Mann kann sie immer einpacken. Allerdings sehe ich ein, dass davon
nicht jeder so ohne weiteres zu ueberzeugen ist: Wir drehen uns im
Kreis. Vermutlich sind mir einfach eine ganze Reihe von Details
unbewusst im Sinn geblieben, die ich in Diskussionen in clc++, csc++
oder clc++m aufgeschnappt habe. Vielleicht ist es auch wirklich das
Umfeld in dem ich programmiere (derzeit bastel ich an einem "Toolkit
for Graph Algorithms", das in die Richtung von STL fuer Graphen geht:
da benutze ich einfach nur in Klassen Pointer, wenn ueberhaupt).
Auf jeden Fall werde ich mich bemuehen, in Zukunft meine Kritik besser
zu motivieren (seitdem ich was auf den Deckel bekommen habe, weil ich
eine abfaellige Bemerkung ueber "PC based operating systems" gemacht
habe, lasse ich das auch besser bleiben...).
Vielleicht sollten wir ueber etwas fundierteres diskutieren... Was
haelst Du z.B. von meinen Vorschlag (in einem anderen Thread), DOCH
einen Konstruktor aus einem anderen aufzurufen :-) Ziemlich nutzlos,
aber ist es wenigstens portable? Aus clc++m habe ich dazu [noch] nichts
gehoert... (und dabei gucke ich schon die ganze Zeit nach neu
eintreffenden Artikeln zum Moderieren: das ist der Vorteil. Ich sehe
einige Artikel viel frueher! Teilweise dauert es 24h eh der Artikel
wieder zurueckverteilt ist, nachdem ich ihn moderiert bei
'netlab.cs.rpi.edu' ins Newssystem eingespeist habe).
--
dietmar.kuehl@uni-konstanz.de
http://www.informatik.uni-konstanz.de/~kuehl
I am a realistic optimist - that's why I appear to be slightly pessimistic
Technical Details
Message-ID:
<4ggkbr$7vr@news.BelWue.DE>Path:
arc1-ca.pugleaf.net!news.belwue.de!uzwil!kuehlReferences:
<3120B25C.2650@fokus.gmd.de> <31229576.0@news.uni-konstanz.de> <pu91i3yvzc.fsf@themroc.colibri.de> <BOP9B96C@wuschel.ibb.schwaben.com> <4gdb6p$i5j@news.BelWue.DE> <W7Q9BM6M@wuschel.ibb.schwaben.com>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!news.belwue.de!uzwil!kuehl From: kuehl@uzwil.informatik.uni-konstanz.de (Dietmar Kuehl) Newsgroups: de.comp.lang.c++ Subject: Re: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen Date: 22 Feb 1996 02:28:11 GMT Organization: Fakultät für Mathematik und Informatik Message-ID: <4ggkbr$7vr@news.BelWue.DE> References: <3120B25C.2650@fokus.gmd.de> <31229576.0@news.uni-konstanz.de> <pu91i3yvzc.fsf@themroc.colibri.de> <BOP9B96C@wuschel.ibb.schwaben.com> <4gdb6p$i5j@news.BelWue.DE> <W7Q9BM6M@wuschel.ibb.schwaben.com> Reply-To: dietmar.kuehl@uni-konstanz.de NNTP-Posting-Host: uzwil.informatik.uni-konstanz.de X-Newsreader: TIN [version 1.2 PL2]