Zeiger und Referenzen
-
Hallo mal wieder,
da ich immer noch Neuling bin und der Auffassung, dass man bei C++ sehr viel mehr hinsichtlich der Sprache denken und überlegen muss als in Java (finde dort kann man sich mehr auf die Umsetzung der Problemstellung konzentrieren und muss sich nicht soviel mit der Sprache und dem Standard auseinandersetzen - nichts desto trotz will ichs ja lernen, C++ meine ich!!!) wollte ich eine Frage stellen, die bestimmt schon oft beantwortet wurde (habe über die Suche dazu leider nix gefunden):
Wie verhält es sich in C++ bei folgender Situation:
In einer Methode erzeuge ich mit
... new ConstructorCall();Einen Zeiger und weise ihn einer privaten Variablen der Klasse zu.
Danach erzeuge ich in selber Methode einige Objekte wie folgt:Object1 o1(); Object2 o1(); ,,.Diese Objektreferenzen setze ich nun über entsprechende Methoden in das Objekt, welches ich über new angelegt habe (Attributsetter) und werlasse nun die Methode.
Die private Klassenvariable hat in dieser Instanz nun einen gültigen Wert, aber was ist mit deren Attributen, die ich als Referenz in einer Methode gesetzt habe nachdem ich die Methode verlassen habe?
Leben die in der privaten Variablen weiter, bis delete() aufgerufen wird?
Wenn es zu diser Frage schon Antworten, FAQs etc. gibt bitte darauf verweisen!
Danke schon mal!
Ciao
-
Reth schrieb:
Diese Objektreferenzen
Ich denke von diesem Gedanken musst Du Dich als Java-Umsteiger zuerst verabschieden. Das sind keine Objektreferenzen, sondern die Objekte selbst. Das heisst sie belegen auf dem Stack genau den Speicher den sie benötigen (anders als "Referenztypen" in anderen Sprachen, wo auf dem Stack in Wirklichkeit nur ein Zeiger liegt).
Diese Objektreferenzen setze ich nun über entsprechende Methoden in das Objekt, welches ich über new angelegt habe (Attributsetter) und werlasse nun die Methode.
Da man Referenzen in C++ nicht zuweisen kann, sondern nur initialisieren, gehe ich davon aus, Du kopierst hier in Wirklichkeit die beiden Objekte in das mit new angelegte. Das heisst es existieren zunächst vier Objekte, zwei auf dem Stack und zwei innerhalb des mit new erzeugten, und bei der Zuweisung wird der Inhalt der beiden Stack-Objekte in das dritte kopiert. Aber das kann anhand eines Codebeispiels deinerseits sicher besser beurteilen

Am Ende der Methode sind o1 und o2 jedenfalls nicht mehr vorhanden.
-
// Objekt selbst ,keine referenz
MyClass oObjekt;//Referenz erzeugen als Adresse des Objekts
// Problem wir der aktuelle Block verlassen in dem oObjekt erzúgt wird
// ist referenc ungütlig
MyClass *pRef = &Objekt;// Lösung:
MyClass *pRef = new MyClass();
-
Hm, da hab ich mir in C++ die Referenzen wohl falsch eingeprägt und muss zusehen, dass ich das korrigiert bekomme!
Ich dachte bisher immer, dass in C++ eine Referenz auf ein Objekt so eine Art unveränderlicher Zeiger ist und nicht eine ganze Kopie auf das Objekt. So dass eine Referenz die Vorteile eines Zeigers bietet (wenig Speicher, Objekt ist nur einmal vorhanden), ohne dessen Nachteile in Kauf zu nehmen (es kann immer anderer Speicher an den Zeiger zugewiesen werden, so dass Objekte verloren gehen können).
Daher auch die Bedingung, dass Referenzen immer auf gültige Objekte zeigen müssen.Dass die Referenz nun eine komplette Kopie des Objektes sein soll haut mich ein bisschen um!
Hier mal ein Codebsp., was ich meinte:
class A { methode(Object1& o1, Object2& o2); } class B { andereMethode(); } B::andereMethode() { A *a = new A(); Object1 o1(); Object2 o2(); a->methode(o1, o2); }Was passiert in Methode a mit o1 und o2 wenn "andereMethode" verlassen wird?
Dass das ganze mit Zeigern funktioniert weiss ich, wollte aber soviel wie möglich Referenzen benutzen (aus o.a. Überlegung zu Referenzen).
Ciao
Edit: Hab gerad beim Durchlesen meiner Antwort gesehen, dass das alles funktioniert, da ich in methode() zwar Referenzen übergebe, aber diese ja keinen Klassenvariablen von A zugewiesen werden können (da diese ja Referenzen sein und damit schon initialisiert sein müssten, oder aber Objekte, die dann eine Kopie darstellen würden - oder? Was würde denn mit solchen Objekten in A passieren, wenn man andereMethode verlässt?).
Aber was ist mit meiner Ansicht über Referenzen in C++ (also die mit & im Parametertyp)? Liege ich hier so total falsch?
-
A a = new A();
geht das denn???
müsste es nicht heißen A *a = new A(); bzw. A* a = new A();?
und a->methode(...); der Aufruf dann sein????
-
@Checker&Murckser:
Stimmt sorry, da hab ich mich vertan!
Korrigiert!
-
Reth schrieb:
@LordJaxom:
Was passiert in Methode a mit o1 und o2 wenn "andereMethode" verlassen wird?Wenn Du die beiden Referenzen nur in methode verwendest kein Problem, da die Methode längst zurückgekehrt ist, wenn andereMethode verlassen wird. Das einzige was schiefgehen könnte ist wenn Du in methode die Adressen der Referenzen nimmst und irgendwo speicherst. Was macht methode denn mit den beiden Referenzen?
Ansonsten macht eine Referenz wohl das was Du meinst dass sie macht

-
Es ist halt immer so ein Kreuz mit den REferenzen, wenn sie nicht richtig erklärt sind. Bei einer Referenz wird in C++ die Adresse des Zielobjektes übergeben (im Assembler ist das eine indirekte Adressierung, und damit 4 Byte).
Gruss Jerry
-
@LordJaxom:
Danke, dann behalt ich mal meine beschriebenen Gedanken zu den Referenzen so bei!@jerry:
Das ist ein Zeiger aber auch, nur dass ich diesem nen neuen Wert zuweisen kann und der Referenz nicht.Ciao
-
@Reth: Der Zeiger ist eine eigenständige Variable, die eine Adresse als Inhalt aufnimmt(Daher veränderbar). Die Referenz wird intern anders dargestellt und ist eine feste Adresse auf das Objekt! Jerry
-
Danke nochmals!
Eine Frage noch:
Kann man denn sowas machen:
void klasse::methode(Param *p) { P& rp = (*p); }?
Ciao
-
P rp = (*p);
//rp -> Objekt auf das der Zeiger zeigt
P *r = &rp;
//r neuer zeiger auf das objekt
aber glaub
P &rp= .. geht nich
weis aber nich genau
-
BorisDieKlinge schrieb:
aber glaub
P &rp= .. geht nich
Natürlich geht das. Da man allerdings den Pointer dereferenziert muss man zuvor sicherstellen, dass dieser auch auf ein gültiges Objekt verweist.
-
@Boris:
P rp = (*p);Erzeugt eine Kopie des Objekts auf das p zeigt.
Der Rest:
P& rp = (*p);geht tatsächlich. Dann ich rp eine Referenz auf das Objekt, auf das p zeigt. Aber Obacht: Das ist der klassische Fall um eine ungültige Referenz zu erzeugen, z.B. wenn p NULL ist oder ins Nirvana zeigt.
EDIT: (s.a. HumeSikkins) die Dereferenzierung ist schon undefiniert, dürfte aber bei den meisten Compilern funktionieren, bis man rp selbst benutzt...
-
Hallo nochmals,
nun muss ich nach langer Zeit nochmal ein bisschen wiederkauen (bin immer noch blutiger Anfänger).
Da ja nun Referenzen zumGlück doch keine komplette Objektkopien sind, habe ich mal eine Frage zum Umgang mit denselben:
Ich habe bei meinem Projekt mehrere Klassen (z.T. komplett statisch), die auf Anforderung Objekte erzeugen und diese auch intern in STL-Containern verwalten, da sie auch verschiedene Zugriffs- bzw. Suchmöglichkeiten auf die erzeugten Objekte anbieten.
Nun hab ich das so implementiert, dass die Methoden, welche die Objekte erzeugen, die Objekte mit new anlegen und den Zeiger in den jew. STL-Containern speichern und auch zurückgeben.
In den Destruktoren der Klassen, welche die Objekte erzeugen werden dann die STL-Container abgelaufen, die darin liegenden Zeiger mit einem delete bedacht und die Container geleert.
Meine Fragen dazu sind nun aber:
1. Was passiert in den statischen Klassen, die ja auch Objekte erzeugen und in statischen STL-Membervariablen ablegen? Wann werden hier die Objekte gelöscht (bzw. deren Zeiger mit delete bedacht)? Beim Beenden des Programmes?
2. Ist es sinnvoller den Objekterzeugungsmethoden als Rückgabewert eine Referenz (wenn möglich konstant) zu geben statt eines Zeigers auf das neu erzeugte Objekt? (Bei einem Zeiger kann ja jeder delete darauf aufrufen!)
Vielen Dank schon einmal
Ciao