 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Boris Glawe Guest
|
Posted: Sun Feb 05, 2006 10:45 pm Post subject: Pointer oder nicht Pointer |
|
|
Hallo,
wenn man Instanzvariablen einer Klasse wie folgt nicht als Pointer implementiert,
class Object{
};
class Example{
public:
Example(Object& o) : object(o){}
private:
Object o;
};
dann werden doch von ein und dem selben Objekt zwei Instanzen gebildet: Einmal
die Instanz auf die die Referenz des Argumentes des Konstruktors zeigt und
einmal die Instanz, die der Konstruktor von Example erzeugt, um seine private
Instanzvariable zu erzeugen.
Das ist doch technisch wie auch semantisch ziemlicher Stumpfsinn!? Ich erhalte
zwei Instanzen von einem Object, obwohl ich eigentlich nur eine Instanz
übergeben wollte. Aus technischer Sicht ist es Platz und Rechenzeitverschwendung.
Außerdem kann man in keiner Weise ausdrücken, dass ein Objekt nicht existiert,
weil es bei Referenzen so etwas wie einen Nullpointer nicht gibt.
Die Lösung ist, auf Referenzen zu verzichten und wieder Pointer zu nutzen und
sich den Speicher der Instanzvariablen wieder dynamisch zu erzeugen.
Damit schmeißt man aber ein ganzes Feature von C++ über Bord.
Was habe ich falsch verstanden?
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Mon Feb 06, 2006 1:01 am Post subject: Re: Pointer oder nicht Pointer |
|
|
Boris Glawe wrote:
| Quote: | Hallo,
wenn man Instanzvariablen einer Klasse wie folgt nicht als Pointer
implementiert,
class Object{
};
class Example{
public:
Example(Object& o) : object(o){}
private:
Object o;
};
dann werden doch von ein und dem selben Objekt zwei Instanzen gebildet:
Einmal die Instanz auf die die Referenz des Argumentes des Konstruktors
zeigt
|
Die wird nicht gebildet. Die mußt du übergeben.
| Quote: | und einmal die Instanz, die der Konstruktor von Example erzeugt, um
seine private Instanzvariable zu erzeugen.
Das ist doch technisch wie auch semantisch ziemlicher Stumpfsinn!? Ich
erhalte zwei Instanzen von einem Object, obwohl ich eigentlich nur eine
Instanz übergeben wollte. Aus technischer Sicht ist es Platz und
Rechenzeitverschwendung.
|
Nicht unbedingt. Wenn das Objekt klein ist, kann eine Kopie schneller
erledigt sein als das dynamische Allokieren und Deallokieren und weniger
Speicher brauchen, weil der Overhead des Speichermanagements wegfällt.
Abgesehen davon werden solche Kopiervorgänge auch oft durch den Compiler
wegoptimiert.
| Quote: | Außerdem kann man in keiner Weise ausdrücken, dass ein Objekt nicht
existiert, weil es bei Referenzen so etwas wie einen Nullpointer nicht
gibt.
|
Du kannst aber einfach einen zweiten Konstruktor einführen, der keine
Referenz auf ein Objekt annimmt. Oder mit Default-Werten arbeiten:
Example(const Object& o = Object()) : object(o){}
Ein vernünftiger Compiler optimiert die Kopie hier weg.
| Quote: | Die Lösung ist, auf Referenzen zu verzichten und wieder Pointer zu nutzen
und sich den Speicher der Instanzvariablen wieder dynamisch zu erzeugen.
|
Oder - so man wirklich empirisch nachgewiesen hat, daß die Kopie tatsächlich
nennenswerten Overhead produziert - man macht sich eine Klasse, bei der
mehrere Instanzen sich die gleichen Daten teilen können, z.B. mit
Referenzzählung.
| Quote: | Damit schmeißt man aber ein ganzes Feature von C++ über Bord.
Was habe ich falsch verstanden?
|
Du bist etwas voreilig bei dem Schluß: Kopie = riesiger Overhead.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Bob Hairgrove Guest
|
Posted: Mon Feb 06, 2006 1:01 am Post subject: Re: Pointer oder nicht Pointer |
|
|
On Sun, 05 Feb 2006 18:45:40 +0100, Boris Glawe <boris@boris-glawe.de>
wrote:
| Quote: | wenn man Instanzvariablen einer Klasse wie folgt nicht als Pointer implementiert,
class Object{
};
class Example{
public:
Example(Object& o) : object(o){}
private:
Object o;
};
dann werden doch von ein und dem selben Objekt zwei Instanzen gebildet: Einmal
die Instanz auf die die Referenz des Argumentes des Konstruktors zeigt und
einmal die Instanz, die der Konstruktor von Example erzeugt, um seine private
Instanzvariable zu erzeugen.
Das ist doch technisch wie auch semantisch ziemlicher Stumpfsinn!?
|
Je nach dem, was man mit dem Objekt anstellt...deshalb sind ja beide
Möglichkeiten erlaubt!
| Quote: | Ich erhalte
zwei Instanzen von einem Object, obwohl ich eigentlich nur eine Instanz
übergeben wollte. Aus technischer Sicht ist es Platz und Rechenzeitverschwendung.
|
Es kommt ganz darauf an, wer das Objekt besitzen sollte ... d.h. vor
allem, wer das Objekt wieder zerstören sollte.
| Quote: | Außerdem kann man in keiner Weise ausdrücken, dass ein Objekt nicht existiert,
weil es bei Referenzen so etwas wie einen Nullpointer nicht gibt.
Die Lösung ist, auf Referenzen zu verzichten und wieder Pointer zu nutzen und
sich den Speicher der Instanzvariablen wieder dynamisch zu erzeugen.
Damit schmeißt man aber ein ganzes Feature von C++ über Bord.
Was habe ich falsch verstanden?
|
Falsch verstanden hast Du nur, dass Pointers durchaus ihre
Daseinsberechtigung haben! C++ ist schliesslich nicht Java ... so
wenig wie C++ auch nicht "C++/CLI" ist.
--
Bob Hairgrove
NoSpamPlease (AT) Home (DOT) com
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Andreas Seik Guest
|
Posted: Tue Feb 07, 2006 10:02 pm Post subject: Re: Pointer oder nicht Pointer |
|
|
Boris Glawe wrote:
| Quote: | class Object{
};
class Example{
public:
Example(Object& o) : object(o){}
private:
Object o;
};
|
Ist das kleingeschriebene objekt ein Tippfehler?
Wenn Du keine Kopie erzeugen willst geht folgendes:
class Example{
public:
Example(Object& o_in) : o(o_in){}
private:
Object o&;
};
| Quote: | Außerdem kann man in keiner Weise ausdrücken, dass ein Objekt nicht
existiert, weil es bei Referenzen so etwas wie einen Nullpointer nicht
gibt.
|
Ich finde die Unterscheidungsmöglichkeit sehr angenehm.
Will ich sicherstellen, das Member initialisiert sind, nehm' ich Referenzen.
Möchte ich auch mit nicht Initialsierten Werten umgehen, nehm' ich Pointer.
Inzwischen nehme ich fast nur noch Referenzen; es ergibt sich einfach kaum
eine Gelegenheit für Pointer.
Gruß
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Sat Feb 11, 2006 3:06 am Post subject: Re: Pointer oder nicht Pointer |
|
|
| Quote: |
Damit schmeißt man aber ein ganzes Feature von C++ über Bord.
Was habe ich falsch verstanden?
Du bist etwas voreilig bei dem Schluß: Kopie = riesiger Overhead.
|
class Object{
public:
Object() : value(0) {cout << "Example() constructor called" << endl; }
int getValue(){ return value;}
void setValue(int v) {value = v; }
private:
int value
};
class Example{
public:
Example(Object& o) : object(o){ }
private:
Object object;
};
int main()
Object o; // nur hier wird Konstruktor von Object aufgerufen
cout << "Value nach Objekterzeugung: " << o.getValue() << endl;
Example e(o);
e.getObject().setValue(5);
cout << "Value nach setValue: " << o.getValue() << endl; // => 0
cout << "Value nach setValue in example: " << e.getObject().getValue() << endl;
// => 5
/*hier ist der Ende des Gültigkeitsbereiches von o, weswegen automatisch sein
Destruktor aufgerufen wird
es ist leicht ein Fall zu konstruieren, in dem e weiterlebt und - wie im Text
unten angenommen - der Speicher auf den "value"
zeigt schon freigegeben ist. value ist hier kein Pointer, im Text habe ich
das aber angenommen*/
}
Mir ist nicht so ganz klar, was genau in meinem Beispiel passiert. Es geht mir
nicht nur um den Overhead, sondern mehr um die Probleme, die aus der Existenz
zweier Objekte (obwohl semantisch nur eins existiert ) entstehen.
Ich habe in den Körper des Object Konstruktors mal ein paar cout Anweisungen
gepackt um zu sehen, wie häufig tatsächlich ein Konstruktor aufgerufen wird.
Zudem habe ich ein paar Instanzvariablen (int) zur Klasse Object hinzugfügt,
deren Wert ich verändert habe, um zu prüfen, ob tatsächlich zwei verschiedene
Objekte existieren.
Ergebnis ist dir/euch bestimmt bekannt: Es wird nur ein einziges mal der
Konstruktor von Object aufgerufen. Die Instanzvariable object in Example wird
also nicht durch den Konstruktor erstellt, sondern durch eine Kopieraktion.
Durch das Verändern des Instanzvariable "value" in den jeweiligen Object
Instanzen konnte ich verifizieren, dass tatsächlich zwei Objekte im
Arbeitsspeicher existieren, da ich zwei verschiedene Werte für "value" speichern
konnte.
Jetzt kommt wieder die Frage ins Spiel, die ich schon einmal gestellt habe: Was
ist, wenn ich ausdrücken möchte, dass ein Objekt einer Instanz nicht existent
ist? Beispielsweise könnte ich ausdrücken wollen, dass die Instanz "value" gar
nicht existiert. Referenzen kennen so etwas wie einen Nullpointer nicht. Also
trifft die Wahl für den Typ meiner Instanzvariablen auf pointer. Übergebe ich
nun dem Konstruktur von Example eine Instanz von Object als Referenz, dann wird
intern eine Kopie dieser Instanz gemacht und damit auch eine Kopie des
*Pointers* value, der auf einen beliebigen Speicherbereich zeigt. Dieser
Speicher wurde aber im Objectkonstruktor manuell reserviert, weswegen er jetzt
nur einmal existiert.
Ab jetzt habe ich zwei Pointer auf den selben Speicherbereich. Da ich mich
entschieden habe, mit Pointern zu arbeiten, muss ich im Destruktor auch für die
Freigabe des Speichers sorgen. Der Zeitpunkt zu dem der Destruktor aufgerufen
wird, ist aber nicht mehr unter meiner Kontrolle! Es kann jederzeit passieren,
dass die Instanz von Object, die dem Example() Konstruktor übergeben wurde,
gelöscht wird (z.B. durch Verlassen des Gültigkeitsbereiches), aber die Instanz
von Object, die in einer Example Instanz gespeichert ist, noch weiterlebt..
Allerdings wurde durch den Destruktor der ersten Instanz von Object schon der
Speicher des "value" freigegeben, wodurch ich einen ungültigen Pointer habe und
einen Absturz nicht mehr vermeiden kann.
Ich habe hier aus einer ganz alltäglichen Situation heraus einen Absturz
kreiiert, indem ich problemorientiert objektorientiert programmiert habe. Mir
ist nicht ganz bewusst, wie man mit Referenzen stabil programmieren möchte.
Sobald auch nur eine Klasse einen Pointer als Instanzvariable hat, ist ein
Absturz vorprogrammiert.
Denke ich zu kompliziert oder kann es sein, dass man sich beim Entwurf von C++
etwas in den Netzen der Komplexität verfangen hat?
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Jens Müller Guest
|
Posted: Sat Feb 11, 2006 4:06 pm Post subject: Re: Pointer oder nicht Pointer |
|
|
Boris Glawe schrieb:
| Quote: | Jetzt kommt wieder die Frage ins Spiel, die ich schon einmal gestellt
habe: Was ist, wenn ich ausdrücken möchte, dass ein Objekt einer Instanz
nicht existent ist? Beispielsweise könnte ich ausdrücken wollen, dass
die Instanz "value" gar nicht existiert. Referenzen kennen so etwas wie
einen Nullpointer nicht. Also trifft die Wahl für den Typ meiner
Instanzvariablen auf pointer. Übergebe ich nun dem Konstruktur von
Example eine Instanz von Object als Referenz, dann wird intern eine
Kopie dieser Instanz gemacht und damit auch eine Kopie des *Pointers*
value, der auf einen beliebigen Speicherbereich zeigt. Dieser Speicher
wurde aber im Objectkonstruktor manuell reserviert, weswegen er jetzt
nur einmal existiert.
|
Willst Du, daß er zweimal existiert, also deep statt shallow copy
gemacht wird?
| Quote: | Ab jetzt habe ich zwei Pointer auf den selben Speicherbereich. Da ich
mich entschieden habe, mit Pointern zu arbeiten, muss ich im Destruktor
auch für die Freigabe des Speichers sorgen.
|
Der dann gemeinsam benutzt wird ... Also doch eher was mit Referenzzählung.
Oder halt eine deep copy, also das referenzierte Objekt im
Copy-Konstruktor mitkopieren.
Zu
| Quote: | Allerdings wurde durch den Destruktor der ersten Instanz von Object
schon der Speicher des "value" freigegeben, wodurch ich einen
ungültigen Pointer habe und einen Absturz nicht mehr vermeiden kann.
|
Ich verstehe irgendwie nicht ganz dein Problem. Wenn Du Pointer
verwendest, darfst du natürlich kein OBjekt freigeben, das woanders noch
benötigt wird. Wenn Du geeignete Referenzen benutzt, sollte das Zählen
der Referenzen und Freigeben, wenn keine Referenzen mehr da sind,
automatisch gehen. Destruktor und delete, also Deallokation des
Speichers, sind IMO auch erstmal konzeptionell unterschiedliche Dinge.
Der Destruktor wird natürlich aufgerufen, bevor der Speicher dealloziert
wird.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Sun Feb 12, 2006 5:06 pm Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
| Quote: |
Ich verstehe irgendwie nicht ganz dein Problem.
|
Ich habe jetzt einfach mal den Fall, den ich meine in Code gestrickt (Komentare
im Code:
####################################################################################################
#include <iostream>
using namespace std;
/*unwichtige Klasse, sie dient weiter unten einfach nur dazu, mit "new"
instanziert zu werden*/
class Value{
public:
Value(int x) : v(x){}
private:
int v;
};
/*Diese Klasse speichert einen Pointer "value", bei dem ich später provoziere,
dass er zu früh gelöscht wird */
class Object{
public:
Object(int v): value(new Value(v)){
cout << "Object(int v): Konstruktor aufgerufen" << endl;
cout << "Object(int v): Nach Erzeugung von value: " ; printValueAddress();
}
~Object(){
cout << "~Object(): Destruktor aufgerufen" << endl;
delete value;
value = NULL;
cout << "~Object(): Nach Löschen von value: "; printValueAddress();
}
void printValueAddress() { cout << "Wert von value: " << value << endl; }
private:
Value* value;
};
class Example{
public:
Example(Object& o) : object(o){
cout << "Example(Object& o): Konstruktor aufgerufen" << endl;
}
~Example(){
cout << "Example(Object& o): Destruktor aufgerufen" << endl;
}
Object& getObject(){ return object; }
private:
Object object;
};
Example* createExample(int v){
Object o(v);
return new Example(o);
// Hier wird automatisch o's Destruktor aufgerufen und damit auch die
Instanzvariable "value" deleted
}
int main(){
Example* e = createExample(19);
// der Pointer "value" in e's object zeigt jetzt auf einen Speicherbereich, der
schon längst wieder freigegen ist
e->getObject().printValueAddress();
return 0;
}
####################################################################################################
Vielleicht besteht mein Fehler darin, die Object Instanz in Example wie oben
geschehen zu definieren. Ich habe eben mal ausprobiert, die Object Instanz in
Example als Referenz zu implementieren:
class Example{
public:
[...]
private:
Object& object; // hier ist der Unterschied zu vorher
};
jetzt ist zwar das Problem gelöst, dass ich einen ungültigen Pointer habe, aber
direkt nach der Instanzierung von "Example* e" ist "value" ein Nullpointer -
was nicht der Semantik des Codes entspricht.
Welche Kapitel muss ich nacharbeiten?
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Jens Müller Guest
|
Posted: Sun Feb 12, 2006 8:06 pm Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
Boris Glawe schrieb:
| Quote: |
jetzt ist zwar das Problem gelöst, dass ich einen ungültigen Pointer
habe, aber direkt nach der Instanzierung von "Example* e" ist "value"
ein Nullpointer - was nicht der Semantik des Codes entspricht.
Welche Kapitel muss ich nacharbeiten?
|
Du siehst hoffentlich ein, daß Dein Beispiel von der Sprachdefinition
genau das macht, was es soll, oder?
Der Compiler macht nur das, was Du ihm sagst.
Sowas wie
| Quote: | Example* createExample(int v){
Object o(v);
return new Example(o);
// Hier wird automatisch o's Destruktor aufgerufen und damit auch
die Instanzvariable "value" deleted
}
|
finde ich daher nun wirklich höchstgradig merkwürdig. Du allozierst ein
Object auf dem Stack, steckst es irgendwo rauf, und wunderst Dich dann,
wenn Deine Verweise nicht mehr gültig sind?
Dein Problem hier ist doch nicht, das der Destruktor von o aufgerufen
wird, sondern daß dein o gar nicht über das Ende der Ausführung von
createExample hinaus existieren kann, weil es auf dessen Stackframe liegt.
Object* o = new Object(v);
return new Example(*o);
sollte doch problemlos gehen?
Was mußt Du nacharbeiten? Nun, Du darfst halt nichts vernichten, was Du
noch brauchst, das kannst Du zB mit Referenzzählung machen. Aber wenn du
halt was vernichtest, was Du noch brauchst, kann da doch C++ nichts für.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Sun Feb 12, 2006 10:06 pm Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
Ich meine, das nachzuholende Kapitel gefunden zu haben: Ich muss mir einen
Kopierkonstruktor defnieren, der die Daten, auf die mein Pointer "value" zeigt,
an die Stelle meiner neuen Object Instanz kopiert, an die mein neuer Poinster
"value" zeigt. Richtig?
Konnte mir überhaupt noch jemanf bis hierhin in meiner Argumentation folgen?
Wenn nicht, dann habe ich zum Thema Kopierkonstruktor gleich die nächste Frage:
(fast der gleiche Code, wir auch oben schon)
class Value{
public:
Value(int x) : v(x){}
int getInt(){ return v; }
private:
int v;
};
class Object{
public:
Object(const Object& o) {
/*Möglichkeit 1*/
value = new Value( o.getValue()-> getInt() );
/*Möglichket 2 wäre der Einsatz von memcopy*/
}
private:
Value* value;
};
Benutzt ihr Möglichkeit 1 oder Möglickeit 2? Oder vielleicht eine ganz andere
Lösung?
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Jens Müller Guest
|
Posted: Sun Feb 12, 2006 10:06 pm Post subject: Re: Pointer oder nicht Pointer |
|
|
Andreas Seik schrieb:
| Quote: | Wenn Du keine Kopie erzeugen willst geht folgendes:
class Example{
public:
Example(Object& o_in) : o(o_in){}
private:
Object o&;
};
|
Sieht gut aus - natürlich darf man dann nicht wie der OP was auf dem
Stack alloziertes als o_in übergeben ...
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Sun Feb 12, 2006 10:06 pm Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
Jens Müller wrote:
| Quote: | Boris Glawe schrieb:
jetzt ist zwar das Problem gelöst, dass ich einen ungültigen Pointer
habe, aber direkt nach der Instanzierung von "Example* e" ist "value"
ein Nullpointer - was nicht der Semantik des Codes entspricht.
Welche Kapitel muss ich nacharbeiten?
Du siehst hoffentlich ein, daß Dein Beispiel von der Sprachdefinition
genau das macht, was es soll, oder?
Der Compiler macht nur das, was Du ihm sagst.
|
Ich weiß. Ich beschwere mich auch nicht über das, was der Compiler macht,
sondern frage mich - nachdem ich dem Thema "Referenzen" lange genug ausgewichen
bin - wie man mit Referenzen vernünftig programmiert, ohne dass man sich solche
Fallen stellt, wie ich sie oben konstruiert habe. Meine Konstruktion ist nicht
an den Haaren herbeigezogen. Deine unten vorgeschlagene Lösung weicht wieder auf
die Verwendung von Pointern aus, so dass ein Vorteil der Referenzen wieder weg
ist. Die Lösung scheint ein Kopierkonstruktor zu sein, wie ich es in einem
Posting gerade eben geschrieben habe. Wenn ich die Klasse Object mit einem
Kopierkonstruktor versehe, dann ist die Speicherwaltung der Instanzvariablen
wieder in der Klasse gekapselt und ich bin wieder zufrieden.
| Quote: | Sowas wie
Example* createExample(int v){
Object o(v);
return new Example(o);
// Hier wird automatisch o's Destruktor aufgerufen und damit auch
die Instanzvariable "value" deleted
}
finde ich daher nun wirklich höchstgradig merkwürdig. Du allozierst ein
Object auf dem Stack, steckst es irgendwo rauf, und wunderst Dich dann,
wenn Deine Verweise nicht mehr gültig sind?
|
Ja bei der Verwendung von Referenzen als Parameter für Konstruktoren, scheint es
üblich zu sein, dass man Objekte übergibt, die auf dem Stack liegen. Wenn ich
sie auf dem Heap haben wollte, dann musste ich sie mit new allozieren und müsste
wieder auf Pointer ausweichen.
| Quote: | Dein Problem hier ist doch nicht, das der Destruktor von o aufgerufen
wird, sondern daß dein o gar nicht über das Ende der Ausführung von
createExample hinaus existieren kann, weil es auf dessen Stackframe liegt.
Object* o = new Object(v);
return new Example(*o);
sollte doch problemlos gehen?
|
Sobald ich den Gültigkeitsbereich verlasse, muss ich manuell ein delete
Ausführen, wodurch der Speicher, auf den der in o enthaltenen Pointer zeigt,
wieder freigegeben würde. Ob ich das manuell oder autamatisch mache, macht
keinen Unterschied.
Vielen Dank für die Antworten und die Mühen!!
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Thomas J. Gritzan Guest
|
Posted: Mon Feb 13, 2006 12:06 am Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
Boris Glawe schrieb:
| Quote: | Konnte mir überhaupt noch jemanf bis hierhin in meiner Argumentation
folgen?
Wenn nicht, dann habe ich zum Thema Kopierkonstruktor gleich die nächste
Frage:
(fast der gleiche Code, wir auch oben schon)
class Value{
public:
Value(int x) : v(x){}
int getInt(){ return v; }
private:
int v;
};
class Object{
public:
Object(const Object& o) {
/*Möglichkeit 1*/
value = new Value( o.getValue()-> getInt() );
/*Möglichket 2 wäre der Einsatz von memcopy*/
|
igitt!
| Quote: | }
private:
Value* value;
};
Benutzt ihr Möglichkeit 1 oder Möglickeit 2? Oder vielleicht eine ganz
andere Lösung?
|
Möglichkeit 3: Einen Kopierkonstruktor. Der bietet sich da prima an.
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Jens Müller Guest
|
Posted: Mon Feb 13, 2006 12:06 am Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
Boris Glawe schrieb:
| Quote: | Sowas wie
Example* createExample(int v){
Object o(v);
return new Example(o);
// Hier wird automatisch o's Destruktor aufgerufen und damit auch
die Instanzvariable "value" deleted
}
finde ich daher nun wirklich höchstgradig merkwürdig. Du allozierst ein
Object auf dem Stack, steckst es irgendwo rauf, und wunderst Dich dann,
wenn Deine Verweise nicht mehr gültig sind?
Ja bei der Verwendung von Referenzen als Parameter für Konstruktoren,
scheint es üblich zu sein, dass man Objekte übergibt, die auf dem Stack
liegen. Wenn ich sie auf dem Heap haben wollte, dann musste ich sie mit
new allozieren und müsste wieder auf Pointer ausweichen.
|
Aber bei
Object* o = new Object(v);
return new Example(*o);
wird doch kein Pointer übergeben, sondern der vom Pointer referenzierte
Wert (vom Typ Object, nicht Object*) by reference?!
Oder habe ich da einen Denkfehler?
Und natürlich willst Du Objekte haben, die auf dem Heap liegen. Objekte,
die auf dem Stack liegen, darfst du nur übergeben, wenn ihre Lebenszeit
garantiert endet, bevor diejenige des Stackframes endet. Und das ist
wohl in deinem Beispiel kaum der Fall, es geht ja gerade darum, an den
Aufrufer ein Example zurückzugeben, in dem das Object enthalten ist.
Wenn das Object auf dem Stack alloziert würde, wäre es nach dem return
gar nicht mehr vorhanden.
Sowas kannst Du machen, wenn du den Wert auf dem Stack erzeugst, dann
irgendwie innerhalb der Funktion irgendwohin übergibst, und vor dem
return wird das Objekt, wo du es reingesteckt hast, nicht mehr benötigt.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Mon Feb 13, 2006 11:06 am Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
| Quote: |
class Object{
public:
Object(const Object& o) {
/*Möglichkeit 1*/
value = new Value( o.getValue()-> getInt() );
/*Möglichket 2 wäre der Einsatz von memcopy*/
igitt!
}
Benutzt ihr Möglichkeit 1 oder Möglickeit 2? Oder vielleicht eine ganz
andere Lösung?
Möglichkeit 3: Einen Kopierkonstruktor. Der bietet sich da prima an.
|
Ist das oben kein Kopierkonstruktor? Oder wird er erst zu einem
Kopierkonstruktor, wenn man eine Initialisierungsliste angibt?
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
Boris Glawe Guest
|
Posted: Mon Feb 13, 2006 11:06 am Post subject: Re: Pointer oder nicht Pointer (vielleicht habe ich es jetzt |
|
|
| Quote: |
Aber bei
Object* o = new Object(v);
return new Example(*o);
wird doch kein Pointer übergeben, sondern der vom Pointer referenzierte
Wert (vom Typ Object, nicht Object*) by reference?!
Oder habe ich da einen Denkfehler?
|
Du dereferenzierst o bei der Übergabe an den Konstruktor von Example. Damit wird
das Objekt selbst und nicht der Pointer kopiert.
Beim Verlassen des Gültigkeitsbereiches hast du zwei Instanzen von einem Object
o. Teil der beiden Instanzen ist eine Pointer value, die beide auf den selben
Speicher zeigen, da dieser Pointer 1:1 kopiert wurde.
Am Ende musst du dein mit new alloziertes Object manuell wieder löschen und
gibst damit den Speicherbereich frei, auf den "value" zeigt. Dieses Freigeben
muss der Destruktor machen, da der Konstruktor die Reservierung vorgenommen hat.
Damit hat aber die Kopie von o einen Pointer auf einen eben frei gegebenen
Speicherbereich.
| Quote: | Und natürlich willst Du Objekte haben, die auf dem Heap liegen. Objekte,
die auf dem Stack liegen, darfst du nur übergeben, wenn ihre Lebenszeit
garantiert endet, bevor diejenige des Stackframes endet. Und das ist
wohl in deinem Beispiel kaum der Fall, es geht ja gerade darum, an den
Aufrufer ein Example zurückzugeben, in dem das Object enthalten ist.
|
gut, das Argument sehe ich ein. In vielen Tutorials wurden aber so
selbstverständlich Objekte an Konstruktoren übergeben, die auf dem Stack liegen,
dass ich c++'s Speicherverwaltung etwas zuviel zugemutet habe. Solche Konstrukte
sollte man also nur machen, wenn man auch den Kopierkonstruktor richtig
implementiert hat.
| Quote: |
Wenn das Object auf dem Stack alloziert würde, wäre es nach dem return
gar nicht mehr vorhanden.
Sowas kannst Du machen, wenn du den Wert auf dem Stack erzeugst, dann
irgendwie innerhalb der Funktion irgendwohin übergibst, und vor dem
return wird das Objekt, wo du es reingesteckt hast, nicht mehr benötigt.
|
Ok, so weit ist die Welt in Ordnung. Allerdings scheint mir dieser Fall nicht
sehr praxisrelevant zu sein. Ansonsten müsste ich in der main()Funktion alle
Möglichen Variablen auf den Stack legen, um sie dann an all meine benutzten
Objekte weiterzureichen. Das gibt eine sehr lange main Funktion :-)
Grüße Boris
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|