Wahl des Typs eines std::vector
-
Wenn meine Klasse einen vector und eine Methode in der Form
std::vector<Foo> foos; Foo & createFoo(); // Mit absicht kein constWie würde man am geschicktesten und am performancesparendsten ein neues Foo auf das foos werfen und dessen Referenz returnen?
Foo & createFoo() { Foo f; foos.push_back(f); return foos.back(); }Das geht, aber hier ist für mich eine Erzeugung von Foo zuviel und irgendwie unnötig, da Foo erzeugt wird und dann direkt kopiert wird.
Kann man das umgehen, ohne auf Pointer zu wechseln? Oder geht das nur mit Pointern oder Smart Pointer (natürlich die ohne ownership
)?
-
Erm, mal wieder die grundsätzliche Frage: Ist das wirklich ein Performanceengpass? Ansonsten würde ich an sowas keinen Gedanken verschwenden. Mal abgesehen davon ist das was Du da treibst u.U. gefährlich. Das hängt davon ab, was Du mit der zurückgegebenen Referenz treibst.
-
Seikilos schrieb:
Das geht, aber hier ist für mich eine Erzeugung von Foo zuviel und irgendwie unnötig, da Foo erzeugt wird und dann direkt kopiert wird.
Das dürfte aber wegoptimiert werden. Evtl. kannst Du dem Compiler die Optimierung noch vereinfachen, indem Du ein temporäres Objekt übergibst.
Foo & createFoo() { foos.push_back(Foo()); // oder: foos.resize(foos.size() + 1); return foos.back(); }EDIT: Ok, zumindest meine Compiler optimieren es nicht weg.
-
Wie meinst du das? Es ist absicht, dass es nicht const ist und relevante Teile davon sind protected. Alles andere soll direkt modifiziert werden können, da es keine Accessoren für Foo gibt
-
Seikilos schrieb:
Wie meinst du das? Es ist absicht, dass es nicht const ist und relevante Teile davon sind protected. Alles andere soll direkt modifiziert werden können, da es keine Accessoren für Foo gibt
Rödelst Du dabei zufällig auf einer bestimmten foo-Referenz rum, wärend Du mit createFoo() weitere foos in den Vektor packst?
-
Oh, meinst du damit, dass ne ref auf vector.back() immer auf den letzten zeigen wird (konnte dazu nichts ind er doku finden)? Wenn ich mit der Ref davon arbeite und ein element pushe, so ändert sich die referenz automatisch und zeigt auf das neue letzte element?
Wenn, wie umgeht man das? Mit Foo & const createFoo() ?
Edit: http://www.cplusplus.com/reference/stl/vector/back.html
Unlike member vector::end, which returns an iterator just past this element, this function returns a direct reference.
-
Seikilos schrieb:
Oh, meinst du damit, dass ne ref auf vector.back() immer auf den letzten zeigen wird (konnte dazu nichts ind er doku finden)? Wenn ich mit der Ref davon arbeite und ein element pushe, so ändert sich die referenz automatisch und zeigt auf das neue letzte element?
Nein, aber wenn Du ein neues Element hinten anfügst, könnte der Vector vergrößert werden. Damit werden alle Elemente umkopiert und alle Referenzen, die Du Dir zuvor geholt hast werden ungültig.
-
Nein. Die Referenz bleibt schon bestehen. Nun ist es aber so, dass ein
std::vectoreine Kapazität für eine bestimtme Anzahl an Elementen reserviert hat (ob diese nun bereits vorhanden sind oder nicht, spielt keine Rolle). Diese lässt sich mitstd::vector::capacity()herausbekommen.
Wenn man ein Element einfügt, und dadurch mehr Elemente im Vektore gespeichert werden müssen als aktuell an Kapazität vorhanden ist, wird die Kapazität vergrößert. Hierfür wird der Vektor komplett neu (mit größerer Kapazität) angelegt und die Elemente kopiert. Zeiger und Referenzen auf Elemente werden hierdurch höchstwahrscheinlich ungültig, da der Vektor sich nicht mehr an der gleichen Speicherstelle befindet.
-
Wie würde man dieses Problem gescheit vorbeugen können?
Ich weiß nicht, wieviele Features kommen werden, brauche aber eine gültige Referenz auf die einzelnen Objekte
-
1. Du könntest statt einer Referenz den Index zurückgeben, und Dir vor jedem Zugriff (gern auch vor einer Serie von Zugriffen) die Referenz holen und nach dem Zugriff wieder vergessen.
2. Du könntest den Container wechseln. std::list garantiert z.B., dass Referenzen beim Einfügen und Löschen gültig bleiben (ausser die Referenz auf ein gelöschtes Objekt, natürlich).
-
Danke,
ich werde erstmal list probieren.Hast du nen link bezüglich list, ich konnte bei cplusplus.com nicht aus der list definition rauslesen, dass sie sich so verhält