Größe von Referenzen und Zeigern
-
Hallo zusammen,
ich arbeite jetzt schon längere Zeit mit Zeigern und Referenzen. Jedoch weis ich nicht genau wie groß sie sind. Kann mir da einer genaue Zahlen nennen? Eine Integer Variable ist im Normalfall beispielsweise 4 Byte groß.
-
int var; int* ptr = &var; int& ref = var; cout << "int-Pointer hat eine Größe von: " << sizeof(ptr) << endl; cout << "int-Referenz hat eine Größe von: " << sizeof(ref) << endl;Diese Werte werden wohl bei den meisten Zeigern gleich sein auf deinem System. Allerdings können spezielle Zeiger (z.B. auf auf Methoden von Klassen) ganz andere Größen haben - und das je nach Compiler. Am besten du verlässt dich hier nie auf eine fixe Größe

MfG SideWinder
-
Referenzen belegen keinen eigenen Speicher, daher können sie auch gar keine Größe haben.
SideWinder schrieb:
int var; int* ptr = &var; int& ref = var; cout << "int-Referenz hat eine Größe von: " << sizeof(ref) << endl;Diese Ausgabe gibt eher die sizeof von var aus, nicht aber die sizeof der Referenz...
-
referenz ist so gross wie ein ptr. beide in den allermeisten faellen 4 oder 8byte.
-
Nein, Referenzen belegen keinen eigenen Speicher. Außer der Compiler kriegt das nicht besser hin. (was man nicht ausschliessen kann, aber normalerweise sollte es funktionieren) Referenzen sind nur ALIASE einer Variable! Kann man in jedem guten C++-Buch und auch in Bjarne Stroustrups Buch nachlesen.
#include <iostream> int main() { using namespace std; int var; int* ptr = &var; int& ref = var; cout << "int-Pointer hat eine Größe von: " << sizeof(ptr) << endl; cout << "int-Referenz hat eine Größe von: " << sizeof(ref) << endl; cout << "Adresse von var " << &var << " und ref " << &ref << endl; }Ergebnis:
int-Pointer hat eine Größe von: 4 int-Referenz hat eine Größe von: 4 Adresse von var 0013FF64 und ref 0013FF64Compiler: MSVC8.0
var und ref sind ein und das selbe. Also nur einmal 4 byte verbraten und nicht zweimal 4 byte.
-
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.
-
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.
-
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.
ja das stimmt, alle mit 4 (bzw
bytes, sofern man es sonst als const-ref uebergeben wuerde, sollte man eher by value uebergeben, das hilft dem compiler auch sehr beim optimieren weil viele aliasing-annahmen wegfallen.
-
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?
-
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.
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.
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.
-
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?
Bei POD's ist das schon eher ne Stil-/Designfrage. Bei Klassen, dh größeren Objekten, spart man sich so die Kopie der Daten, somit auch den Aufruf von den ganzen C'tors und D'tors ...
-
KasF schrieb:
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?
Bei POD's ist das schon eher ne Stil-/Designfrage. Bei Klassen, dh größeren Objekten, spart man sich so die Kopie der Daten, somit auch den Aufruf von den ganzen C'tors und D'tors ...
Sollte man deshalb im Sicherheitsbereich rumpfuschen? Bei Klassen verwendet man doch Zeiger auch nur nach dem Beispiel
void zeigmirgeldan(kundenkonto *kunde) { }Hierbei werden keine Kopien übergeben, weil meistens C'tors irgendwelche Werte zurücksetzen oder sachen verfälschen, und nicht deshalb, weil man Performance sparen will, oder seh ich das falsch?
-
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
)