Operator << überladen fehlgeschlagen
-
Achso, ich dachte, um dieses Methodenüberschrieben zu verhindern, ist das #ifndef HEADER_H da.
Mit inline funktioniert es auf jeden Fall

-
Fabulus schrieb:
Achso, ich dachte, um dieses Methodenüberschrieben zu verhindern, ist das #ifndef HEADER_H da.
Das ist nur dafür da, dass der Header nicht zweimal in der selben ÜE eingebunden wird, z.B. indirekt über andere Header. Zwei unterschiedÜbersetzungseinheiten werden aber mit zwei völlig unabhängigen Compileraufrufen übersetzt. Der Compiler weiß nicht, ob die Definition in einer anderen ÜE schon vorkommt oder nicht. Und selbst wenn, muss es ja nicht sein, dass die Objektdateien dann auch zusammengelinkt werden.
Darum ist das auch kein Compilerfehler, sondern ein Linkerfehler: erst der Linker erkennt, dass in beiden Objektdateien eine Definition für den op<< steckt und kann beim Zusammenlinken nicht entscheiden, welche von beiden denn aufgerufen werden soll. Merke: der Linker bekommt deinen Code und die include-Guards garnicht zu sehen, er bekommt nur die Objektdateien.
-
Wieso hast du bei deinem Standardkonstruktor nich die Initialisierungsliste genutzt sondern den Konstrukorrumpf?
Ich weiß gehört nicht zum eigentlichen Problem, aber das wurde ja eh schon gelöst;-)Lg freeG
-
Oh, das habe ich wohl unbewusst gemacht, als ich diesen nachträglich hinzugefügt hab... alte Java-Angewohnheit.
-
Ok, dachte schon du hättest vll gedacht dass man die Init-Liste nur nutzen kann wenn man Argumente hat:D
Lg freeG
-
Ich denke nicht, dass hier eine Übergabe per Referenz bzw const-Referenz einen Vorteil brint (da int und kein Klassentyp). Möglicherweise macht das das Pogramm sogar langsamer, um ehrlich zu sein weiß ich es aber nicht.
-
wieso sollte es langsamer werden?!?
bei call by reference wird doch mehr doer weniger nur die adresse übergeben und die ist so groß wie int. ob nun das geklasselte int oder das zeiger int übergeben wird sit doch egal ...
-
Und genau deswegen kann es langsamer werden - um den Wert hinter der Referenz zu bekommen, mußt du jedes Mal diese Adresse auswerten.
-
Selbst wenn du eine Kopie erstellst (Call by Value) muss auch immer noch bei jedem Zugriff auf diese Variable die relative Adresse der Variablen bei Zugriff gesetzt sein und über diese zugegriffen werden.
Während bei Call by Value also eine harte Kopie erstellt werden muss (1:1 Kopie im lokalen Speicher für diesen Block), wird bei Call by Reference nur ein Zweitname bzw die Adresse übergeben.
Der Dereferenzierungsaufwand ist somit der gleiche und Call by Reference ist in jedem Fall performanter.
-
Ich bin zwar nicht wirklich Experte für Assambler-Feinheiten (da mußt du etwas tiefer im Forum nachschauen), aber imho kann indirekte Adressierung durchaus langsamer werden als direkte Adressierung*. Außerdem ist ein int so klein, daß er durchaus in ein Register gepackt werden kann - und dann brauchst du überhaupt keine Speicher-Zugriffe mehr, um sie zu verwenden.
*Bei der Übergabe der Referenz schreibst du die Adresse der Variable in den lokalen Block (was auch nicht weniger Platz einnehmen dürfte als der int-WErt selber) und brauhst anschließend für jede Aktion zwei Lese-Operationen: (1) lies die Adresse der Variablen aus dem Stack, (2) lies den Wert der Variablen von dort, wo die Adresse hinzeigt. Bei der direkten Adressierung entfällt der erste Schritt (wo die lokalen Variablen bezüglich des Stack-Pointers stehen, weiß der Compiler, also muß er diese Adresse nicht mehr irgendwo holen).
PS: Ja, ich weiß, diese Unterschiede fallen shon unter Mikro-Optimierung

-
Du hast bei Referenzen quasi dieselbe Adressierung als sei es eine normale Variable.
Viele Mikrooptimierungen machen eine Große!

-
erstie schrieb:
Du hast bei Referenzen quasi dieselbe Adressierung als sei es eine normale Variable.
Eben nicht - bei einer "normalen" Variable steht die Adresse zur Compilezeit fest (notfalls relativ zum Stack-Pointer), bei einer Referenz kennst du die Adresse erst zur Laufzeit.
(effektiv sind Referenzen nicht mehr als gut getarnte Zeiger - der Compiler verbeitet zwar einige typishe Zeiger-Operationen (z.B. Inhalt auslesen) und führt andere (Dereferenzierung) automatisch durch, aber im fertigen Maschinencode wirst du nicht sehr viele Unterschiede zwischen einem int* und einem int& finden)Viele Mikrooptimierungen machen eine Große!

Wenn du es im großen Maßstab betrachtest, eher nicht :D.
Bei theoretischen Betrachtungen zur Laufzeit fallen konstante Faktoren sowieso unter den Tisch, genauso wie konstanter Overhead (siehe O-Notation). Und in der Praxis sollte man erst an solche Mikro-Optimierungen gehen, wenn man weiß, daß sie in dem Teil des Programms stattfinden, der wirklich die Laufzeit frisst, nicht pauschal bei allen Ecken, die möglicherweise schneller sein könnten.
-
Nein falsch. Du kennst zur Compilezeit nur relative Adressen.
Der Compiler kann ja nicht wissen wo später das Programm im Speicher liegt.Eine Referenz verhält sich nach wie vor wie ein Zweitname auf eine Variable.
Betrachte dir doch mal genauer, was genau eine Variable ist.
Speicher, der reserviert wurd und mittels eines Aliasnamen(Variablennamen) über seine Adresse auf den tatsächlichen Speicher dereferenziert wird.
Vielleicht kannst du ja mal den von dir angeführten maschinencode Posten.
-
erstie schrieb:
Nein falsch. Du kennst zur Compilezeit nur relative Adressen.
Der Compiler kann ja nicht wissen wo später das Programm im Speicher liegt.Dann besteht der Unterschied eben darin, daß du bei der lokalen Variable zur Compilezeit weißt, worauf sich diese relative Adresse bezieht (der Compiler kennt seine Architektur, also kann er fest eincodieren, daß sich der benötigte Wert z.B. 8 Byte vom aktuellen Stack-Pointer entfernt befindet). Bei einer Referenz oder einem Pointer weißt du erst zur Laufzeit, wo im Speicher sich der benötigte Wert befindet, also kannst du die Adresse nicht durch durch ein simples "SP+k" ermitteln.
Betrachte dir doch mal genauer, was genau eine Variable ist.
Speicher, der reserviert wurd und mittels eines Aliasnamen(Variablennamen) über seine Adresse auf den tatsächlichen Speicher dereferenziert wird.
Dieser Variablenname existiert aber nur in deinem Quelltext, beim Prozessor kommt nur noch die Adresse als "SP+k" an.
Bei einer Referenz liegt der tatsächlich reservierte Speicher irgendwo im RAM (wenn überhaupt) und du mußt noch zusätzlich im lokalen Stack-Frame Platz bereitstellen, um zu notieren, wo der Wert steht.Vielleicht kannst du ja mal den von dir angeführten maschinencode Posten.
Kann ich leider nicht, dazu mußt du drei Etagen tiefer nachfragen.
PS: Und dabei beziehe ich noch nicht einmal die Tatsache ein, daß int-Variablen so klein sind, daß der Compiler eventuell gar keinen Speicher für sie reserviert, sondern sie direkt in ein Register packt - mit Referenzen ist das nicht unmittelbar möglich.