Initialisierliste, mit new erzeugtes Objekt



  • Hallo, ich habe ein kleines syntaktisches Problem:

    boost::array<int, 4> test = { 1, 2, 3, 4 };   // ok
    

    Wie funktioniert es, wenn ich das array auf dem Heap anlege? Rein syntaktisch, meine ich. Ich suche also sowas wie

    boost::array<int, 4>* test = new boost::array<int, 4>() = { 1, 2, 3, 4 };
    

    aber es sollte compilieren ­čśë Ich kann ├╝brigens auf die Initialisierung nicht verzichten, da es in Wirklichkeit keine ints sind und auch nichts, was einen Standardkonstruktor hat.

    Danke, an den ersten, der dieses R├Ątsel l├Âsen kann. ­čÖé



  • Soviel ich weiss, ist das nicht m├Âglich. Eventuell hilft dir aber boost::assign::list_of .

    Aber wieso willst du ein statisches Array ( boost::array ist eigentlich nur ein Wrapper f├╝r C-Arrays) dynamisch anlegen? W├Ąre da std::vector nicht eher was?



  • Ich habe sozusagen ein optionales array als member. Es ist ein Quadtree, der Kinder hat oder nicht. Der Member ist ein std::auto_ptr<boost::array<Quadtree, 4>> und kann nat├╝rlich ein nullptr sein, oder ein array der Gr├Â├če 4. Na, wenn's nicht geht, dann verk├╝nstel ich mich jetzt aber auch nicht weiter. Thx.



  • Wenn die Dimension sowieso immer 4 betr├Ągt, k├Ânntest du doch eine eigene Klasse schreiben und entsprechende Konstruktoren bereitstellen. Dann w├Ąrst du auch zus├Ątzlich flexibel, falls du pl├Âtzlich Funktionalit├Ąt hinzuf├╝gen m├Âchtest, und k├Ânntest gleichzeitig etwas von den Zeigern abstrahieren. Ist nur so ein Vorschlag... ­čśë


  • Administrator

    Ganz bl├Âder Vorschlag:

    boost::array<int, 4> const temp = { 0, 1, 2, 3 };
    boost::array<int, 4>* p = new boost::array<int, 4>(temp);
    

    Wom├Âglich ist der Kompiler klug genug, dies wegzuoptimieren ­čśë

    Gr├╝ssli



  • Dravere schrieb:

    Wom├Âglich ist der Kompiler klug genug, dies wegzuoptimieren ­čśë

    Falls nicht (was ich hier bef├╝rchte) hat man viele unn├Âtige Konstruktionen - denk dran, es geht Optimizer nicht um int s. Je nachdem kann sich das beim Quadtree ziemlich negativ auswirken. Abgesehen davon weisst du nicht, ob die Objekte ├╝berhaupt kopierf├Ąhig sind.



  • Sind sie nicht. Der Vorschlag mit der eigenen Klasse: Ich probier's grad, aber ich glaub das wird schei├če. Ich hatte an sowas gedacht:

    class ChildCollection {
    	public:
    		ChildCollection(const Area& parentArea);
    		boost::array<Quadtree, 4>::iterator begin();
    		boost::array<Quadtree, 4>::iterator end();
    
    	private:
    		boost::array<Quadtree, 4> children;
    	};
    

    Aber ich kann das array nat├╝rlich wieder nicht richtig initialisieren. Ich seh's jedenfalls nicht, wie das in der Initialisierliste gehen soll und nen Standardkonstruktor gibts nicht, da es f├╝r den Quadtree auch keinen gibt. Es endet also wieder mit Quadtree* als array-Element, dann kann ich mir aber die eigene Klasse sparen.



  • Muss es unbedingt boost::array sein? Dieser Container scheint mir f├╝r dein Vorhaben ziemlich ungeeignet.

    Die STL-Container fallen auch weg, weil deine Objekte nicht kopierbar sind (Zeiger und SmartPointer sind wahrscheinlich unn├Âtig/m├╝hsam). Naheliegend w├Ąren f├╝r mich die Boost.PointerCointainer, z.B. boost::ptr_vector . Oder du schreibst einen eigenen Container, was allerdings nicht mit wenig Aufwand verbunden ist, wenn du auch Iteratoren unterst├╝tzen willst.

    Ich bin mir allerdings eh nicht ganz sicher, was du genau tun willst. Sollte ChildCollection -Konstruktor nicht vier Parameter haben? Oder erstellst du die Quadtree -Unterb├Ąume erst im Konstruktor selbst?



  • Ich erstelle sie zwangsl├Ąufig erst bei der Konstruktion der ChildCollection, weil sie nicht kopierbar sind. Zeiger wollte ich vermeiden, weil ich sonst wieder einen Destruktor brauche. Klar, das ist alles nicht furchtbar dramatisch, ich frage mich halt was eine wirklich coole L├Âsung w├Ąre.

    Du hast mich immerhin auf ptr_array gebracht, das h├Ârt sich schon mal besser an als alles was ich bisher ausprobiert habe. Kann iterieren, brauche keinen eigenen Destruktor, fast schon geil. Nur die child Quadtrees sind auf dem Heap allokiert. Da komm ich wahrscheinlich nicht drum herum, wenn ich es nicht schaffe, ein Array zu initialisieren. Im Moment ist das meine favorisierte L├Âsung. ­čÖé



  • Hm, boost::ptr_array scheint ein recht guter Kompromiss zu sein, war mir bisher selber nicht bekannt. Ich dachte, die Pointer-Container g├Ąbe es nur als ├äquivalent zu den STL-Containern. ­čÖé

    Die QuadTrees sollten auch auf dem Heap allokiert sein. Ich kann mir vorstellen, dass das Ganze gr├Âsser werden k├Ânnte, und mit dem Heap bist du diesbez├╝glich viel flexibler. Ich denke hingegen eher nicht, dass der Performancenachteil durch dynamische Allokationen derart dramatisch sein sollte...



  • Nat├╝rlich, es sind alles Luxusprobleme, da sind wir uns einig. ­čÖé ptr_array ist auf den ersten Blick komisch. Der Zugriff ist trotzdem ├╝ber Referenzen, jetzt kann ich offenkundig nicht myArray[0] zuweisen, weil dann w├╝rde ich den Quadtree zu kopieren versuchen. Beim ptr_vector isses klar, da w├╝rde ich ein push_back machen. Naja ich geh jetzt schlafen. Vielleicht mache ich morgen eine vollkommen uncoole und einfache L├Âsung. ­čÖé



  • class Foo
    {
        boost::array<boost::optional<Quadtree>, 4> children; // Quadtree muss _nicht_ default konstruierbar sein!
    };
    

    Initialisieren kannst du das dann entweder ├╝ber copy-construction (einfach zuweisen - intern wird dann der copy-ctor aufgerufen), oder ├╝ber eine in-place-factory (was die unn├Âtige Kopie vermeiden w├╝rde).

    p.S.: boost::optional ist IMO eine sehr interessante, aber oft "├╝bersehene" Library.



  • Hmmm. Also optionals statt pointer, das erlaubt evtl. einen noch g├╝nstigeren Zugriff und l├Âst das Destruktor-Problem. Daf├╝r wird die Konstruktion umst├Ąndlicher und das Objekt ist immer so gro├č, auch wenn es keine Kindknoten hat. (Letzteres st├Ârt mich etwas. Aber ok, kann man sich auch ├╝berlegen, thx. EDIT: ne is quatsch, die child-collection gibt's ja nur, wenn der Knoten Kinder hat)

    Ich tendiere jetzt trotzdem eher zum unsch├Ânen array<Quadtree*, 4>, au├čer ich krieg das ptr_array noch zum laufen.


  • Administrator

    @hustbaer,
    Danke f├╝r den Hinweis wegen boost::optional, hab das Ding tats├Ąchlich noch nie gesehen ­čśâ

    @Optimizer,

    #include <boost/ptr_container/ptr_array.hpp>
    
    int main()
    {
    	boost::ptr_array<boost::nullable<int>, 4> arr;
    
    	arr.replace<0>(new int(0));
    	arr.replace<1>(new int(1));
    	arr.replace<2>(new int(2));
    	arr.replace<3>(new int(3));
    
    	return 0;
    }
    

    Wenn du die Objekte im ptr_array nicht wieder auf 0 zur├╝cksetzen m├Âchtest, dann kannst du auf boost::nullable verzichten. Ohne boost::nullable darfst du aber nie bei replace eine 0 ├╝bergeben, sonst hast eine Exception am Hals.

    Gr├╝ssli



  • Danke, ich habe es tats├Ąchlich mit dem replace nicht gecheckt und das IntelliSense checkt auch ├╝berhaupt nichts mehr so dass ich es gar nicht gesehen habe. Das nullable ist h├Ąsslich, aber das brauche ich zum Gl├╝ck nicht. Entweder gibt es alle vier Kinder oder keines, deswegen verwende ich jetzt einen auto_ptr<ptr_array<Quadtree, 4>>.

    Damit hab ich jetzt endg├╝ltig 2 Indirektionen zu den Kindknoten hin, aber ansonsten ist alles ziemlich geil, zum Beispiel kann ich die Kinder alle entfernen indem ich einfach den auto_ptr resette.


Log in to reply