Pointer-Problem?
-
Ich meinte die cpp-Tags. Und offenbar hast du Konstruktoren nicht verstanden, sonst hättest du keine Load-Funktion.
#include <iostream> #include <vector> class Test { public: Test(); ~Test(); void Load(); int* pointer; }; Test::Test() : pointer(nullptr) { } Test::~Test() { delete pointer; } void Test::Load() { pointer = new int(24); } std::vector<Test> vec; void Create() { Test test; test.Load(); vec.push_back(test); } int main() { std::wcout << L"Testprogramm:" << std::endl; Create(); std::wcout << *vec.front().pointer << std::endl; std::wcout << L"Ende!" << std::endl; while(true){}; return 0; }
-
Und drittens hast du die Regel der "Großen Drei" nicht verstanden - beim Kopieren in den vector<> wird eine Kopie von
testangelegt und anschließend das Objekt selbst zerstört (letzteres ruft dessen Destruktor auf).Die einfachste Lösung besteht wohl darin, keine nackten Zeiger zu verwenden, sondern die Informationen sauber zu verpacken (ein int passt auch direkt ins Objekt, ansonsten such mal nach Containern und Smart-Pointern).
-
Und drittens hast du die Regel der "Großen Drei" nicht verstanden - beim Kopieren in den vector<> wird eine Kopie von test angelegt und anschließend das Objekt selbst zerstört (letzteres ruft dessen Destruktor auf).
Habe ich doch als Vermutung geschrieben.
Jungs, das ist nur ein Beispielprogramm. Der wirkliche Code sieht ganz anders aus. Ich habe hier nur als Beispiel einen int-Zeiger genommen. Und dass ich diesen nicht im Konstruktor initialisiere ist so gewollt, da der Wert eben auch "NULL" sein können muss.
Smartpointer wollte ich nach Möglichkeit vermeiden.
-
Wenn du schon weißt, wie die Lösung aussieht, warum fragst du dann noch?
Und ohne Smart-Pointer bleibt dir nichts anderes übrig, als die Kopier-Operationen auch zu definieren - entweder du kopierst den gesamten Block, den die Load()-Funktion reserviert hat, oder du zählst mit, wieviele Objekte diesen Block nutzen. (möglich sind auch Zwischenlösungen, bei denen du erst kopierst, wenn eins der Objekte den Speicherbereich ändern will)
-
Die Lösung kenne ich noch nicht, ich weis aber sehr genau wie ich es nicht lösen möchte ;).
Meinst du damit dass ich dann z.B. den =-Operator überschreiben muss? Das wäre aus meiner Sicht die einfachste Lösung.
-
Ja, genau den mußt du überschreiben - und den Kopier-Konstruktor (
Test::Test(const Test& src);).(das meinte ich dort oben mit den "Großen Drei" - Destruktor, Zuweisung und Kopier-Konstruktor treten grundsätzlich im Team auf.
-
Alles klar, dann werde ich es mal so probieren. Danke euch.
-
C/C++ schrieb:
Jungs, das ist nur ein Beispielprogramm. Der wirkliche Code sieht ganz anders aus.
Warum führst du die Leute dann mit falschem Code aufs Glatteis?
-
Ich habe halt ein Minimal-Beispiel gepostet damit man den Fehler schnell nachvollziehen kann und ihr euch nicht durch unnötig viel Code wälzen müsst. Leider bekommt man hier immer erstmal 5 Posts die dann irgendwelche anderen Dinge im Code bemängeln was auch nicht verkehrt ist, habe schließlich so schon mehrere hilfreiche Tipps hier im Forum bekommen.
-
So, habe jetzt mal versucht das ganze zu implemtieren, allerdings fürchte ich das wird so nicht funktionieren. Denn anstatt eines Int-Zeigers ist der Zeiger vom Typ Base und kann auch auf von Base abgeleitete Objekte zeigen was das Kopieren des Objects im Kopiekonstructor wohl unmöglich macht? Ich habe auch mal versucht anstatt einem Zeiger das Object selber zu nehmen, allerdings wurden dann bei virtuellen Funktionen nur noch die der Base-Klasse aufgerufen. Dann werde ich wohl doch Smart-Pointer brauchen.
-
Wenn du dein komplettes abgeleitetes Objekt kopieren willst, dann sollte das Objekt das besser selber machen - normalerweise in Form einer virtuellen clone()-Methode.
Alternativ verwendest du Referenzzählung (d.h. die Kopien verwenden das selbe Objekt und erst der letzte kümmert sich darum, es wieder zu vernichten).
-
Das mit dem Copy-Konstruktor ist nicht so einfach. Zuerst einmal sind dort 2 Klassen beteiligt. Einmal der (Ich nenn ihn mal) Handler - Das ist die Klasse die den pointer enthält. Und einmal die Base, von der die realen Klassen abgeleitet werden. Damit das richtig funktioniert benötigt der Handler Copy-Konstruktor, Zuweisung und Destruktor. Der Rest geht dann nicht automatisch. Für das Kopieren fügt man der Klasse Base eine virtuelle Funktion (z.B. "Copy") hinzu, was eine mit new erzeugte Kopie von sich selbst zurück gibt.
class Handler { .... Handler(const Handler & source) { pointer = source.pointer->Copy(); } .... Base * pointer; }; class Base { ... virtual Base * Copy() = 0; ... }; class Real : public Base { ... virtual Base * Copy() { return new Real(*this); }; ... };Das kann natürlich noch etwas sauberer ausgeführt werden ...
-
Mit Smart-Pointers, die intelligent genug sind, kann man auch polymorph kopieren. Dann kann man sich das intrusive Clone-Idiom sparen.