Referenz "destructor"?
-
Hi!
Ich hab ein seltsames Problem das ich nicht wirklich nachvollziehen kann.
Die Funktion addReturnPNewGraph soll in der Klasse einen neuen Graph erstellen und mir direkt eine referenz darauf geben. Ziel ist es das unötige Koppieren von daten zu verhindern. Ich will die Daten direkt dorthin schreiben wo sie hinsollen.Aber irgendwie scheint etwas nicht mit der ERSTEN Referenz die ich bekomme nicht zu stimmen...
class SubStreamPlotable { public: SubStreamPlotable(); ~SubStreamPlotable(){}; GraphPlotable& addReturnPNewGraph() { GraphPlotable gp; m_Graphs.push_back(gp); return m_Graphs.back(); } private: vector<GraphPlotable> m_Graphs; }; class GraphPlotable { public: GraphPlotable(){}; ~GraphPlotable(){}; }; int main (void) { SubStreamPlotable sSP; GraphPlotable& g1 = sSP.addReturnPNewGraph(); // nach dieser zeile zeigt g1 auf einen neuen GraphPlotable in sSP. GraphPlotable& g2 = sSP.addReturnPNewGraph(); // nach dieser zeile zeigt g2 auf einen neuen GraphPlotable in sSP. // aber g1 ist jetzt random müll! // als hätte ich es nie initialisiert. GraphPlotable& g2 = sSP.addReturnPNewGraph(); // nach dieser zeile zeigt g3 auf einen neuen GraphPlotable in sSP. // g2 ist komischerweise immer noch initialisiert und funktioniert. // g1 ist immer noch blödsinn. }
-
vector kann seinen Speicher umherkoppieren, wenns in push_back Platz braucht.
-
Wenn du push_back auf einen vector aufrufst, dessen size dadurch dessen capacity übersteigen würde, dann werden sämtliche Iteratoren, Zeiger und Referenzen auf Elemente aus dem vector ungültig. (In der Regel prüft man das aber nicht extra. Nimm einfach an, das alles ungültig wird bei push_back, außer du hast vorher irgendwann ein passendes reserve gemacht)
Viele der anderen Container der Standardbibliothek haben diese Eigenschaft nicht. Aber vermutlich brauchst du diese Eigenschaft auch gar nicht, denn vector gilt nicht umsonst als "Standard"container. Er ist eben für fast alles recht gut. Das herumkopieren innerhalb des vectors ist auch nicht teuer. Wenn die Datenklasse nicht ganz doof gemacht ist, dann kann der vector die Daten verschieben, was sehr flott geht.
Anstatt einer Referenz als Rückgabewert böte sich hier der Index an. Das ist die Art und Weise, wie man beim vector Elemente über Reallokationen hinweg eindeutig wieder finden kann.
-
mit Index meinst du Stelle des Graphen im Vector? Damit ich es mit .at(index) aufrufen kann?
Ich wollte es anders machen weil es mir "schöner" vorkam, aber jetzt ist es klar wieso es nicht geht!
Vielen Dank für die super Erklärung!
-
du kannst auch eine quasi-referenz basteln. etwa so:
class Container { std::vector<int> List; public: class Ref { Container* MyTarget; std::size_t MyIndex; explicit Ref(Container* Target, std::size_t Index) : MyTarget(Target), MyIndex(Index) { } friend class Container; public: operator int& () { return this->MyTarget->List[this->MyIndex]; } }; friend class Ref; Ref Insert(int Value) { this->List.push_back(Value); return Ref(this, this->List.size() - 1); } };ungetestet. bin mir auch nicht sicher ob das so von den friend-reihenfolgen her funktioniert. wenn man sowas ernsthaft machen möchte müsste man das natürlich bisschen besser ausarbeiten. const-correctness sollte dann auch nicht fehlen.
ich persönlich finde die lösung auch nicht wirklich hübsch. ich würde mir eher überlegen, wieso SubStreamPlotable zwar graphen verwaltet aber nicht zugriff darauf erlaubt.