Größe von Referenzen und Zeigern
-
rapso schrieb:
Artchi schrieb:
Nein, Referenzen belegen keinen eigenen Speicher.
wie kann dann das sein:
...und wie sollten zur compiletime diese referenzen aufgeloest werden?
Referenzen sind nur ALIASE einer Variable!
sinnlich ja, technisch sind es pointer.
Es wurde doch angemert, das es Fälle gibt, in denen Referenzen doch wie Zeiger implementiert werden (müssen).
-
rapso schrieb:
Artchi schrieb:
Nein, Referenzen belegen keinen eigenen Speicher.
wie kann dann das sein:
class CFoo { private: int& m_Ref0; int& m_Ref1; int& m_Ref2; int& m_Ref3; public: CFoo(): m_Ref0(*new int), m_Ref1(*new int), m_Ref2(*new int), m_Ref3(*new int) {} }; void RefTest() { CFoo Bla; const int a=sizeof(Bla);//a==16 }und wie sollten zur compiletime diese referenzen aufgeloest werden?
Referenzen sind nur ALIASE einer Variable!
sinnlich ja, technisch sind es pointer.
m_Ref1 etc. zeigen auf "*new int"! Natürlich ergibt das dann 16! Die 16 Bytes sind die "*new int"! Aber die Bytes LIEGEN außerhalb der CFoo-Instanz. Lass dir mal die Adressen von den Referenzen ausgeben. Dann wirst du das selber erkennen.
Beispiel:
#include <iostream> using namespace std; class CFoo { private: int& m_Ref0; int* m_Ptr0; int m_int; public: CFoo(int &i): m_Ref0(i), m_Ptr0(&i) { cout << "Addr von CFoo: " << this << endl; cout << "Addr von CFoo.m_Ref0: " << &(this->m_Ref0) << endl; cout << "Addr von CFoo.m_Ptr0: " << &(this->m_Ptr0) << endl; cout << "Addr von CFoo.m_int: " << &(this->m_int) << endl; } }; int main() { int myInt; cout << "Addr von myInt" << &myInt << endl; CFoo Bla(myInt); }Ergebnis (wichtig sind die Adressenvergleiche!):
Addr von myInt 0013FF60 Addr von CFoo: 0013FF64 Addr von CFoo.m_Ref0: 0013FF60 Addr von CFoo.m_Ptr0: 0013FF68 Addr von CFoo.m_int: 0013FF6CDie Adresse von m_Ref0 ist die von myInt! Das ist der entscheidende Punkt. Wäre m_Ref0 ein Pointer, hätte der Pointer eine andere Adresse. Hat er aber nicht. Weil m_Ref0 keine eigenständige Variable ist. Aber ein Pointer ist eine eigenständige Variable. Schau dir m_Ref0 und myInt an! Und dann m_Ptr0 mit m_Ref0. Nach deiner Theorie, müsste m_Ref0 eine andere Adresse als myInt haben.
Deshalb meckert der Compiler auch, wenn du einer Referenz nicht gleich eine Variable übergibst. Weil von was sollte er dann ein Alias sein?

Meinst du nicht, das es Sinnfrei wäre, Referenzen einzuführen, wenn sie nur Pointer wären? Und wie gesagt, es kann sein, das ein Compiler Referenzen generell als als Pointer implementiert (was aber ein sehr schlechter Compiler wäre!). Vielleicht macht er das sogar nur in bestimmten Situationen/Konstellationen. Ist aber weit vom erdachten Sinn und würde wohl unter "nicht optimal nach Standard" fallen.

-
KasF schrieb:
Ich stelle mir ne Refernz im Speicher immer so vor:
int zahl = 5; /*Speicher --------------- |zahl || 5 | --------------- */ int &ref = zahl; /*Speicher --------------------- |zahl / ref || 5 | -------------------- */Dh die Refernez refernziert nur zusätzlich die Speicherstelle von zahl.
Sehr gute darstellung!

Um es mal zu vervollständigen:
int *ptr = &zahl; /*Speicher --------------------- | ptr || zahl | -------------------- */
-
KasF schrieb:
Deine Referenzen sind auch hier nur Aliase auf unbenannte Objekte. Das heißt wenn Refernzen EIGENEN Speicher belegen würden, dann hättest du einmal in deinem Code den Speicher für new int und einmal den Speicher für die Referenz, dem ist aber nicht so.
die referenzen belegen eigenen speicher, wieso sonst sollte die klasse 16 bytes haben? mit new hast du sicher keinen speicher in der klasse allokiert, du kannst auch gerne folgendes im c-tor machen
CFoor(int* pData): m_Ref0(*pData), m_Ref1(*pData), m_Ref2(*pData), m_Ref3(*pData) { }du weisst also nichtmal ob das nicht ein ptr auf z.b. ein array ist und alle referenzen "zeigen" auf das selbe objekt, trotzdem ist die klasse 16bytes gross. kompilierst du das mit 64bit (also 64bit ptr) ist die klasse 32bytes.
-
Helium schrieb:
Es wurde doch angemert, das es Fälle gibt, in denen Referenzen doch wie Zeiger implementiert werden (müssen).
sie werden immer wie zeiger implementiert und wenn moeglich dann wegoptimiert, das passiert dir auch bei zeigern die "unnuetz" lokal auf ein objekt zeigen (und du keine zeigerarithmetik machst).
-
TravisG schrieb:
Hierbei werden keine Kopien übergeben, weil meistens C'tors irgendwelche Werte zurücksetzen oder sachen verfälschen
Wie können C'tors irgendwelche Sachen zurücksetzen oder verfälschen die es noch gar nicht gibt
Schließlich sind die C'tors der Beginn eines Objektlebens.Beispiel:
class Lo { std::string str; public: Lo() { } }; void blub( Lo obj ) { } void blaa(const Lo& obj) { } int main() { Lo sum; blub(sum); // sum wir kopiert, Aufruf string() und CopyCtor-Lo blaa(sum); // kein Aufruf } // Ja ich verwende lieber bla und blub und so, statt foo, bar etc.Wie man sieht kann man sich so bei größeren Objekten jede Menge sparen ...
-
rapso schrieb:
die referenzen belegen eigenen speicher, wieso sonst sollte die klasse 16 bytes haben? mit new hast du sicher keinen speicher in der klasse allokiert, du kannst auch gerne folgendes im c-tor machen
Schau dir doch mal das erste Posting von Artchi auf dieser Seite an, da steht auch nochmal wieso es 16 Bytes hat ...
rapso schrieb:
du weisst also nichtmal ob das nicht ein ptr auf z.b. ein array ist und alle referenzen "zeigen" auf das selbe objekt, trotzdem ist die klasse 16bytes gross.
Ja klar ist die Klasse 16 Bytes groß. Sizeof versucht von allen Membern die größe zu erfahren, dabei trifft er auf die ganzen m_Ref's. Bei vier m_Ref's trifft er dreimal auf dein p_date und einmal auf dein *new int.
Edit->Regel: Benutze nie sizeof, wenn Refernzen im Spiel sind ...
-
Standard: http://www.kuzbass.ru:8086/docs/isocpp/decl.html#dcl.ref - Punkt 3 schrieb:
It is unspecified whether or not a reference requires storage
Somit ist wohl die Dikussion beenden

( Ich bin trotzdem dafür das 99% der Compiler für Referenzen keinen eigenen Speicher bereitstellen
)
-
TravisG schrieb:
webmaster1987 schrieb:
Vielen dank, ich wollte bei den ganzen Übergabeparametern mal wissen wie effektiv das ganze funktioniert, beispielsweise ist ein / eine Zeiger / Referenz auf eine normale integer Zahl dann genau so groß wie die Daten an sich, lohnt sich also nicht unbedingt in diesem Fall Zeiger / Referenzen zu benutzen.
Ist das nicht eher eine Stilfrage, als eine Frage der Performance? Wieso sollte man Zeiger auf Variablen oder Objekte übergeben, wenn man nur Information und an den Daten ohnehin nichts verändern will?
Ich denke schon wenn man große Objekte übergeben will vergrößert man den benötigten Speicher um die Größe des Objekts ansonsten nur um diese 4 Byte pro Zeiger / Referenz. Dadurch kann man viel einfacher kalkulieren wie viel Speicher das Programm später braucht.
-
KasF schrieb:
rapso schrieb:
du weisst also nichtmal ob das nicht ein ptr auf z.b. ein array ist und alle referenzen "zeigen" auf das selbe objekt, trotzdem ist die klasse 16bytes gross.
Ja klar ist die Klasse 16 Bytes groß. Sizeof versucht von allen Membern die größe zu erfahren, dabei trifft er auf die ganzen m_Ref's. Bei vier m_Ref's trifft er dreimal auf dein p_date und einmal auf dein *new int.
Edit->Regel: Benutze nie sizeof, wenn Refernzen im Spiel sind ...
dann ueberlade new und allokier CFoo mit new, es werden 16bytes gebraucht, eben weil die references genau wie pointer behandelt werden, denn sie sind auch nicht mehr als beschnittene ptr. da zu diesem zeitpunkt der ctor noch nicht aufgerufen wuerde, kannst du auch nichts an objektinformationen haben, die 4byte/ref sind immer (bei 32bit) vorhanden.
zur not schau dir das mal mit ptr und mal mit ref in assembler an, in jeder kombination die du willst, es wird der selbe code generiert werden. ob ref oder ptr ist fuer den compiler genau so irrelevant fuer den code wie const/nicht sonst, das ist nur abstrakte sprach-syntax
sowas wiechar bla; char* pFoo=&bla; *pFoo = 0;wird genau so auf nur 1byte wegoptimiert wie es bei references waere.
und falls du auch mal lust hast zu sehen worauf die references zeigen, einfach
class CFoo { private: union { struct { int& m_Ref0; int& m_Ref1; int& m_Ref2; int& m_Ref3; }; struct { int* m_Ptr0; int* m_Ptr1; int* m_Ptr2; int* m_Ptr3; }; }; public: CFoo(int* pData): m_Ref0(*pData), m_Ref1(*pData), m_Ref2(*pData), m_Ref3(*pData) { m_Ptr0=0; } };ausprobieren, da kannst du auch ne reference auf 0 setzen... klar ne sprachvergewaltigung, aber auch der beweis dass references nur ptr sind.
-
so wie ich C++ einschätze, ist 'sizeof' mit referenzen undefiniert

-
Ich zitiere mich nochmal selbst:
KasF schrieb:
Standard: http://www.kuzbass.ru:8086/docs/isocpp/decl.html#dcl.ref - Punkt 3 schrieb:
It is unspecified whether or not a reference requires storage
Somit ist wohl die Dikussion beenden

Wenn es nicht definiert ist ob eine Refernz Speicher oder keinen Speicher belegt, dann ist wie pale dog auch schon sage, sizeof() auf Refernzen undefiniert.
Also brauchen wir hier doch gar nicht weiter darüber diskutieren, ob sie nun Speicher belegen oder nicht ...
-
Hi,
was vermutlich zu der Verwirrung beiträgt, ist die Verkürzung von "Eine Referenz besitzt keine eigene Adresse und sie kann ohne eigenen Speicherverbrauch implementiert werden" zu "Eine Referenz hat keinen Speicher"...
Letzteres ist eine nette Eselsbrücke für verschiedene Eigenschaften von Referenzen, aber eben auch kein "Spez-Gesetz".
Gruß,
Simon2.