<vector> soll für jedes Element den Konstruktor aufrufen, aber wie?
-
Scarabol schrieb:
Ich MUSS die Daten ja nicht kopieren, aber ein guter Kopierkonstruktor setzt voraus das ich es mache, oder?
Wieso willst du kopieren?
Wieso meinst du dass du einen Copy-Ctor brauchst?
-
Na, weil vector<templ> den Ctor benutzt. Muss ich ihn auch definieren, damit ich korrekte templ Objekte erhalte.
MfG
Scarabol
-
Und wieso willst du
vector<T>verwenden?
vector<T>ist für teuer zu kopierendeTtotal ungeeignet.Nimm nen Pointer-Container, oder nen
vector<shared_ptr<T>>.
-
Sorry, aber ich versteh nur noch Bahnhof...
MfG
Scarabol
-
Wenn du einen vector auf eine Klasse nimmst statt auf Zeiger auf die Klasse, wird bei jedem Einfügen der copy-ctor der Klasse aufgerufen, was die Zeit des Einfügens ziemlich groß macht. Das muss nicht schlimm sein, darüber musst Du Dir aber bewusst sein.
Wenn Dir das zu teuer ist, solltest Du ptr_vector<T> nehmen (der zerstört deine Objekte am Ende wieder) oder vector<shared_ptr<T>>, wenn Du T noch außerhalb der Klasse nutzt, es aber keine zentrale Instanz gibt, welche verantwortlich für die Zerstörung ist (oder wenn ptr_vector<T> aus irgendeinem Grund nicht unterstützt wird). vector<T*> ist auch in Ordnung, wenn der vector nicht verantwortlich für die Zerstörung sein soll.
hustbaer:
Wieso findest Du das denn so schlimm?
-
Naja schlimm...
Ich finde es sinnlos. Ganz speziell in seinem Fall wo es um Texturen geht.Warum?
Weil es Symptombekämpfung ist.
Weil es schlechter Stil ist, und er sich sowas gar nicht angewöhnen sollte.
Weil er sich damit weitere Probleme schafft, die man vermutlich wieder nur mit unsauberen Hacks lösen kann, was wieder zu Problemen führt uswusf.Warum ich das alles denke?
Weil für mich Texturen ganz klar eine Identität haben, also "class types" und keine "value types" sind. Und die haben in einem Vektor nunmal nix verloren, da ein Vektor Objekte "by value" kopiert (und das nicht nur beim erstmaligen Einfügen!), und damit ihre Identität vernichtet.
Alle mir bekannten 3D APIs arbeiten mit Referenzen (Zeigern, Smart-Pointern etc.) auf Texturen. Wenn ich eine Textur in einen Texture-Slot stecke, dann stecke ich da den Zeiger rein, die eigentliche Textur (der "Wert") wird dabei nicht kopiert. Das selbe gilt für Render-Targets.
Wenn sich nun aber die Adresse der Textur ändern kann, dann gibt's Probleme. Die Textur könnte gerade als Render-Target ausgewält sein, oder in einem Texture-Slot stecken. Wenn man dann rendert wird nicht die "neue" Textur bzw. das "neue" Render-Target verwendet, das nach z.b. einer Reallokation im Vektor steckt, sondern die alte, die ursprünglich dem 3D Device übergeben wurde. Das führt dann im Ideallfall zu Grafikfehlern und schlimmstenfalls zu Abstürzen.
Auch wird es dadurch unmöglich, irgendwo Referenzen auf die Textur zu halten. z.B. in irgendwelchen Game-Objekten. Man müsste stattdessen mit irgendwelchen IDs/Indexen/... arbeiten, und sich die Textur jedes mal wenn man sie braucht über diese IDs/... holen. D.h. man bastelt sich die Referenz-Semantik nach, die man gerade vernichtet hat, indem man den falschen Container verwendet hat.
Und das alles nur um
std::vector<T>stattboost::ptr_vector<T>oderstd::vector<std::tr1::shared_ptr<T>>verwenden zu können.Und da ich mir keine Vorteile vorstellen kann, die die oben skizzierten Probleme aufwiegen, halte ich das für Murks.
----
Ansonsten, etwas allgemeiner: auch wenn es sich um teuer zu kopierende "value types" handelt halte ich
std::vector<T>für unpassend. Und zwar weil jedes eingefügte Objekt im Schnitt 2-3 mal kopiert wird (vorausgesetzt dass man nie Elemente löscht). 1x beim Einfügen selbst, und weitere ~~ 1-2 mal (je nach Vektor-Implementierung) durch das "Umkopieren" wenn der Vektor wächst. Da das beim Fenster hinausgeworfene Rechenzeit ist, halte ich es für schlecht. Vor allem wenn man sich keine Vorteile dadurch erkauft. Und was für Vorteile ein Vektor im Vergleich zu einem Pointer-Vektor bei teuer zu kopierenden Elementen haben könnte, weiss ich nicht. Falls dir einer einfällt, lass es mich wissen
-
Hi,
Nagut, also bei Grafikengines ist es ja nun so, dass hin und wieder auch die Grafikbibliothek das eigentliche Speichern uebernimmt. Deswegen stecke ich meine Textur sehr wohl in eine map, weil die aber auch nur die ID haelt, ueber welche OpenGL angesprochen werden kann.
Gut, sobald Objekte in einen Renderzyklus gelangen oder von mehr als einer Seite via Zeiger angesprochen werden muessen, ist der Zeiger natuerlich klar.
Rein aus Interesse jetzt Mal als Randthema: Wieso koennte vector etwas umschieben, wenn er waechst? Weil er den Speicher sonst nicht mehr zusammenhaengend speichern kann? Eigentlich bin ich bisher davon ausgegangen, dass vector garantiert, dass darauf gerichtete Zeiger gueltig bleiben, egal, wie man vergroessert.
Vorteile bei Nutzung von automatischen Variablen statt Zeigern gibt es ja genug wie automatische Speicherverwaltung, Entlastung des Heaps ([url="http://c-plusplus.net/forum/viewtopic-var-t-is-274631.html"]in einem anderen Thread[/url], wo es um etwas Aehnliches ging, zeigte sich der ja auch begrenzt) oder direkter Zugriff auf die Variablen ohne Indirektion, was bei der geringen Anzahl von Zugriffen natuerlich vernachlaessigbar sein sollte.
- Und ja, ich habe gelesen, dass Du geschrieben hast, dass es um Vorteile gibt, welche die Nachteile aufwiegen. Darum stimme ich Dir schon zu, dass hier Pointer mehr Sinn machen, wenn man die Textur tatsaechlich in der Klasse speichert, um die Ladezeiten fuer den Benutzer zu verringern.
Die value type und class type-Begriffe sind sehr praktisch, das werde ich mir Mal im Kopf behalten.

-
Eisflamme schrieb:
Wieso koennte vector etwas umschieben, wenn er waechst? Weil er den Speicher sonst nicht mehr zusammenhaengend speichern kann? Eigentlich bin ich bisher davon ausgegangen, dass vector garantiert, dass darauf gerichtete Zeiger gueltig bleiben, egal, wie man vergroessert.
Nein, Zeiger auf vector-Elemente bleiben nicht gültig, da wie Du selbst schon erahnst, der vector umkopieren muss, wenn er seine reservierte Größe erreicht hat. Das kann mit
std:::vector<>::reserve()beeinflusst werden.
-
Warum muss ich wenn ich folgendes schreibe mehr als nur "class test;" angeben?
Vorher:
class test; class var { // ... private: test * _key; };Nachher:
#include "test.h" class var { // ... private: test _key; };Macht es Sinn meine Codes wie oben zu ändern, um auf die Pointer zu verzichten?
Nachteil währe, dass ich statt "class test;" jedesmal die kompletten Header einfügen müsste.MfG
Scarabol
-
Du solltest diesen Code nicht nutzen, nur um darauf zu verzichten, Header einzubinden.
Wenn Du sowieso aus irgendwelchen Gründen einen Pointer nutzen musst, solltest Du natürlich die Vorwärtsdeklaration nutzen.
-
Hi,
ich benutze für jede meiner Klassen eine Header Datei.
1. Daher die Frage wann macht es Sinn "Vorwärtsdeklaration und Pointer" oder "Headerdatei und keinen Pointer" zu benutzen?
2. Wie muss ich folgenden Code umschreiben, um nicht einen Pointer benutzen zu müssen?
class test { // ... private: vector<myclass> * _pointer; // der Vektor soll nach dem Konstruktor 180 Elemente besitzen/groß sein wie auch immer :-) };MfG
Scarabol
-
Scarabol schrieb:
ich benutze für jede meiner Klassen eine Header Datei.
Was das übliche Vorgehen sein sollte.
Scarabol schrieb:
1. Daher die Frage wann macht es Sinn "Vorwärtsdeklaration und Pointer" oder "Headerdatei und keinen Pointer" zu benutzen?
Diese Frage ist so direkt nicht zu beantworten.
1. Musst du Vorwärtsdeklaration verwenden, wenn es ansonsten zu Kreuzabhängigkeiten kommt.
2. Wenn die Objekte groß sind, sollte man es sich ebenso überlegen.
3. Wenn man allgemein die Linkabhängigkeiten reduzieren will, und nicht zum Handle-Body Idiom/Pimpl greift.Scarabol schrieb:
2. Wie muss ich folgenden Code umschreiben, um nicht einen Pointer benutzen zu müssen?
Ich habe den Thread nur teilweise überflogen, bin aber der Meinung das du hier noch immer den vector falsch verwendest.
1. Niemals ein using namespace im Header verwenden.
2. Warum ein Zeiger auf einen Vector, wahrscheinlich meinst du eher ein Vector von Zeigern.
3. Falls dein vector immer 180 Elemente enthalten soll, würde ich vermutlich eher zum std::tr1::array (<array>) greifen.
-
Scarabol schrieb:
1. Daher die Frage wann macht es Sinn "Vorwärtsdeklaration und Pointer" oder "Headerdatei und keinen Pointer" zu benutzen?
Ich verwende nie Zeiger, es sei denn es gibt gute Gründe Zeiger zu verwenden. Eine Headerdatei nicht einbinden zu müssen sehe ich dabei normalerweise nicht als guten Grund an. All things being equal also eher "Headerdatei und keinen Pointer".
2. Wie muss ich folgenden Code umschreiben, um nicht einen Pointer benutzen zu müssen?
class test { // ... private: vector<myclass> * _pointer; // der Vektor soll nach dem Konstruktor 180 Elemente besitzen/groß sein wie auch immer :-) };#include "myclass.h" class test { public: // du kannst den konstruktor natürlich genau so gut im .cpp file definieren. // die "initializer-list" steht dabei immer bei der definition, nicht bei der deklaration test() // die "initializer-list": : _vec( 180, // initiale grösse myclass() // template für die initialen elemente (kann weggelassen werden, // dann wird ein element default-konstruiert, und das dann als template verwendet, // d.h. dann N mal kopiert um die initialen elemente zu konstruieren ) // siehe http://www.cplusplus.com/reference/stl/vector/vector/ { } // ... private: vector<myclass> _vec; };p.S.: oops, wir drehen uns im Kreis, das hatten wir ja schon

Also nochmal: du kannst Elemente nicht derart in einen Vektor stecken, dass sie nicht kopiert würden. Geht nicht.
-
ok nächste blöde Frage:
Warum sollte ich kein "using namespace" in einer Headerdatei benutzen bzw. darf ich dann in der Implementierung drauf los usen?
MfG
Scarabol
-
Scarabol schrieb:
Warum sollte ich kein "using namespace" in einer Headerdatei benutzen
Überlege Dir, was für einen Effekt die using-Direktive hat.
Überlege Dir, was für einen Effekt die #include-Direktive hat.
Zähle 1 und 1 zusammen.
-
using namespace würde auf alle Dateien angewendet in die ich meine Headerdatei include.
Währ das schlimm?
Ok sagen wir einfach ich machs nicht mehr...MfG
Scarabol
-
Scarabol schrieb:
using namespace würde auf alle Dateien angewendet in die ich meine Headerdatei include.
Und das führt leider nicht allzu selten zu Namenskonflikten, gerade in größeren Projekten...
Grundsätzlich kann man zu "using namespace" sagen:
1. Nicht im Header (oder allgemein: in Dateien die man inkludiert)
2. Hinter alle Includes
3. Möglichst so lokal wie möglich
-
Scarabol schrieb:
using namespace würde auf alle Dateien angewendet in die ich meine Headerdatei include.
Währ das schlimm?
Ja, das wäre ziemlich schlimm.