Article View: de.comp.lang.c++
Article #1682Re: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen
From: Ullrich von Bassewitz
Date: Sun, 25 Feb 1996 23:18
Date: Sun, 25 Feb 1996 23:18
224 lines
12131 bytes
12131 bytes
[Vorsicht, lang (leider)]
Ich versuche mal, die ganze Diskussion ueber Stilhinweise auf einen
Meta-Level zu heben, weil das rumgemache in Details IMHO recht wenig bringt.
Das kann ich mir natuerlich trotzdem nicht verkneifen, aber erstmal etwas
allgemeiner.
Also:
Wenn ich jemandem Hinweise geben will, wie er etwas besser machen kann, dann
gibt es zwei Moeglichkeiten:
a. Entweder ich mache es anders, weil ich es eben anders mache. Dann kann
ich das schreiben, es bleibt aber jedem selber ueberlassen, was er
macht.
b. Oder es gibt tatsaechlich echte, nachweisbare Gruende dafuer, warum man
etwas so und nicht anders machen sollte.
Dein Hinweis in einem anderen Thread, dass "void main()" eine sehr unkluge
Deklaration ist faellt eindeutig unter letzteres. Was ist aber mit Deinen
Stilhinweisen?
IMHO fallen diese eindeutig unter a., sollten also etwas anders formuliert
werden. Es sei denn, Du kannst tatsaechlich nachweisen (und nicht nur durch
Behauptungen), dass durch Verwendung Deiner Hinweise "bessere" Programme
entstehen (besser soll hier heissen: schneller fertiggestellt [Kosten],
fehlerfreier [Kosten] und besser wartbar [Kosten]). Das Problem ist doch,
dass jeder Prophet einer neuen Sprache oder auch nur Stilrichtung behauptet,
dass dadurch "bessere" Programme entstuenden - die meisten koennen das aber
nicht nachweisen.
Solange kein solcher Nachweis existiert faellt das alles unter a. und man
kann verschiedener Meinung darueber sein. Gibt es tatsaechliche, echte
Gruende, dann faellt es unter b. und es waere fuer jeden Programmierer sehr
klug, die Hinweise zu beruecksichtigen (natuerlich ist es oft nicht so
eindeutig, aber man kann sich ja bemuehen).
Deine Aussage war: "char*" ist schlecht, die Verwendung dieses Konstrukts
erzeugt "schlechte" Programme (exakter: Programme, die nach den oben
aufgestellten Kritieren schlechter sind, als ein Programm, das "char*" nicht
verwendet).
Ist das tatsaechlich so? Mir ist keine Untersuchung in dieser Richtung
bekannt - aber heben wir das ganze mal auf einen etwas hoeheren Level: Wenn
dem so waere, dann muessten ja C++ Programme generell "besser" (im oben
definierten Sinne) sein, als C Programme, weil in C Programmen eben
grundsaetzlich "char*" verwendet wird, in C++ Programmen dagegen in vielen
Faellen nicht.
D.h. man koennte sich auch fragen: Sind C++ Programme bessere Programme? Und
hier heisst - sowohl nach den Untersuchungen die ich kenne, als auch meiner
persoenlichen Erfahrung nach - die Antwort eindeutig: NEIN.
Persoenliche Erfahrung: Meine Projekte in C oder Pascal haben weder eine
erhoehte Fehlerhaeufigkeit, noch eine schlechtere Wartbarkeit als meine C++
Programme. Es faellt mir in C++ etwas leichter, grosse Projekte zu managen,
weil die Hilfsmittel der Sprache zur Modularisierung besser sind, der Re-Use
Faktor ist bei C++ geringfuegig besser, aber das war's auch schon. Bei
meinen Assembler-Programmen ist es dagegen eindeutig, dass ich ca. um den
Faktor 2 mehr Fehler mache und dass die Erstellung wesentlich laenger
dauert.
Untersuchungen: Wer mir hier gerade einfaellt ist DeMarco, der in einem
Kommentar ueber seine "Kriegsspiele fuer Programmierer" (gemeint ist eine
Art Programmierwettbewerb) schreibt, es gaebe *keine* Korrelation zwischen
der Qualitaet der Loesung und der Wahl der Programmiersprache. Kann sich
jemand vorstellen, der Linux-Kernel waere besser (im oben definierten Sinne),
wenn er nicht in C, sondern in C++ geschrieben waere? Ich nicht (trotz aller
char* und void*).
Deine Argumentation in allen Ehren, aber ein bischen habe ich auch das
Gefuehl, Du bist etwas in den Grenzen der Sprache befangen. Wenn Speicher
Leaks tatsaechlich ein echtes Problem bei einer Applikation darstellen (und,
entgegen landlaeufiger Meinung sind sie das in vielen Faellen nicht), warum
nimmst Du nicht einfach einen Garbage Collector? Dann bist Du ohne viel
Rumgemache alle Sorgen los, und vor allem: Du bist sie wirklich komplett
los, auch dann, wenn Deine Klassen (die ja mit Pointern handeln) Fehler
enthalten. Und ja, es gibt inzwischen Loesungen, die bis auf wenigen Code
portabel und soweit ich weiss auch echtzeitfaehig sind. Fuer das Problem
Speicher Leaks heisst die adaequate Loesung nun eben mal GC, auch wenn C++
von sich aus keine GC anbietet.
Nicht, dass ich Deine Hinweise nicht interessant finde, aber Du solltest sie
IMHO nicht so als absolut gueltig darstellen. Es ist Deine Meinung, weiter
nichts. Wenn Du natuerlich Argumente hast wie "Laut einer Untersuchung von
Prof. Dr. Dr. F. Bar sinkt die Lebenserwartung von Programmierern bei
Verwendung von char* wesentlich", dann fallen Deine Hinweise eben unter b.
(aber sonst nicht :-).
Und weil ich gerade schon mehr in's Detail gegangen bin, auch das noch:
> [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...]
Meiner Erfahrung nach ist es Unfug, (signed) int zu verwenden bei Variablen,
die per Definitionem eigentlich keine negative Zahlen enthalten sollten. Ein
Beispiel aus einem etwas laenger zurueckliegenden Projekt:
Es war bei uns im Team Vereinbarung, dass Funktionen ihre Parameter und die
Werte, mit denen sie arbeiten, zuerst komplett auf Gueltigkeit pruefen,
damit Fehler so frueh wie moeglich bemerkt werden. Ich hatte eine Funktion
geschrieben, die mit einer Variable namens "IndexPulse" gearbeitet hat, das
war die Anzahl von Pulsen, die eine Scheibe in dem zu steuernden Pruefstand
pro Umdrehung erzeugt. Etwas was definitiv nicht negativ sein kann.
Folglich stand bei mir, bevor ich die Variable anderweitig angefasst habe
ein "PRECONDITION (IndexPulse <= 4)", weil es nur Scheiben mit dieser
maximalen Anzahl an Loechern gab, alles andere musste also Unfug sein.
Dummerweise hatte aber jemand die Variable als int deklariert und es ist
prompt eine negative Zahl (weil nicht initialisierte Variable) durch-
gerutscht, die an anderer Stelle einen Fehler verursacht hat, nach dem
ich ziemlich lange gesucht habe (deshalb habe ich das auch noch in guter
Erinnerung :-).
Das Problem liegt darin, dass die Variable von ihrem Ursprung her impliziert,
dass es eben keine negativen Werte geben kann (negative Loecher gibt es eben
nicht :-), und entsprechend habe ich sie behandelt.
Meine Regel ist deshalb "wenn etwas eigentlich nicht negativ werden kann,
dann soll es auch nicht als signed Wert repraesentiert werden". Wenn Du so
willst, dann ist die Abbildung einer Groesse, die in der Realitaet nicht
negativ werden kann auf einen signed eine unexakte Abbildung.
Das ist natuerlich nur meine Meinung. Es waere auch eine Regelung denkbar,
dass *alles* als signed deklariert wird, dann weiss jeder (oder sollte es
wissen), dass auf negative Werte geprueft werden muss. IMHO ist es
einfacher, direkt unsigned zu nehmen.
> 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?
Da class string den String prinzipiell immer auf den Heap packt ist wohl
klar, woher der Performance Unterschied kommt. Stell Dir folgende Funktion
vor:
int StrCmp1 (const string& lhs, const string& rhs);
// Compare two strings
und
int StrCmp2 (const char* lhs, const char* rhs);
// Compare two string
Wenn Du einen Aufuf hast, wie:
if (StrCmpX ("foo", "bar") == 0) { /* ... */ }
dann werden das eine mal einfach zwei Zeiger uebergeben, das andere Mal
werden zwei Objekte konstruiert (dazu wird Speicher auf dem Heap belegt und
der String dort rein kopiert), nach dem Aufruf wird der belegte Speicher
wieder freigegeben.
> 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.
Ich habe nicht gesagt, dass die niedrigere Performance tatsaechlich eine
Rolle spielt, das tut sie in den meisten Faellen nicht (auch wenn 99% aller
Programmierer fest davon ueberzeugt sind, dass genau ihr Programm mit -O9
uebersetzt werden muss, und dass Bounds Checking bei Arrays des Teufels ist,
weil es zwar Bugs abfaengt, aber die Performance drueckt).
Wenn Du einen Test haben willst, nimm obigen Code (vergiss aber nicht, den
Optimierer auszutricksen, indem Du beide Strings im StrCmpX Aufruf als
extern deklarierst und die Implementation der beiden StrCmp Routinen in ein
anderes Modul packst. Ein Test macht keinen Sinn, wenn der Optimierer Dir
Deine ganze Testumgebung wegoptimiert :-)
> 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...
Das Problem ist nicht die Uebergabe, sondern dass strings so implementiert
sind, dass die Daten auf dem Heap liegen. Das kann in bestimmten
Konstellationen (wie die oben) zu einer recht lausigen Performance fuehren.
> 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
Tja, reingefallen (aber troeste Dich, so ging's mir auch :-).
Natuerlich laesst sich ein Objekt mittels placement new in das Shared Memory
legen. Aber rate mal, was passiert, wenn Du von einem anderen Programm (das
natuerlich auch Zugriff auf das SM haben muss) virtuelle Methoden aufrufst?
Stichwort VMT (oder vtable) Zeiger...
> 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
Natuerlich kann man Pointer immer einpacken. Die Frage ist, ob es Sinn
macht, d.h. ob dabei bessere (im sehr viel weiter oben definierten Sinne)
Programme rauskommen.
> 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
Dazu habe ich leider zu wenig Ahnung von so esoterischen Features. Ich habe
zwar den Draft zum neuen Sprachstandard hier rumliegen (700 Seiten, C++ ist
wirklich eine Monster-Sprache), und auch mehrfach (kopfschuettelnd) darin
rumgelesen, aber um Deine Loesung zu durchschauen, dazu reicht es eben
trotzdem nicht. Ich bin eben letzten Endes bloss ein Anwender...
Gruss
Uz
P.S.: Was haeltst Du von einem beiderseitigen "Abruestungsabkommen" auf
Artikel mit nicht mehr als 100 Zeilen? :-)
--
Ullrich von Bassewitz uz@ibb.schwaben.com
Technical Details
Message-ID:
<VNV9BSBG@wuschel.ibb.schwaben.com>Path:
arc1-ca.pugleaf.net!wuschel.ibb.schwaben.com!not-for-mailReferences:
<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> <4ggkbr$7vr@news.BelWue.DE>Show Full Headers
Complete Article Headers
Newsgroups: de.comp.lang.c++ Path: arc1-ca.pugleaf.net!wuschel.ibb.schwaben.com!not-for-mail From: uz@wuschel.ibb.schwaben.com (Ullrich von Bassewitz) Subject: Re: Q: gcc 2.7.1: Aufruf einer Konstruktormethode aus einer anderen Date: 25 Feb 1996 23:18:29 GMT 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> <4ggkbr$7vr@news.BelWue.DE> Message-ID: <VNV9BSBG@wuschel.ibb.schwaben.com> Reply-To: uz@ibb.schwaben.com Organization: Ingenieurbuero von Bassewitz X-Newsreader: TIN [version 1.2 PL2]