Was taugt Boost?



  • Pointer direkt versuch ich auch zu vermeiden. Ich hab mir sogar eine kleine ptr Klasse gebastelt, die mir das handeln von Pointern abnimmt. Also so, dass ich Speicherzugriffe im Debug Modus vorher auf gültigkeit kontrollieren kann.

    Shared Pointer nutze ich eigentlich überall, weil einem das viel Kopfzerbrechen spart. Ich bin ein großer Fan von Dingen, die sich selbst aufräumen. Ich muss aber sagen, dass der Loki Smartpointer flexibler ist, als das was boost/stdlib bietet (ich nutze aber eigentlich trotzdem immer die boost/stdlib-smartptrs).



  • Ich glaube Loki nutzt niemand in der Praxis *g*



  • @Kingruedi: Das klingt ja interessant. Alle pointer durch einfache smart-pointer ersetzen, die einem im debugmodus Überprüfungsmöglichkeiten bieten. Könntest du das pointer Klassentemplate im Ansatz mal zeigen? Ich meine wie prüft man einen pointer auf seine gültigkeit, außer auf Null?



  • mathik schrieb:

    ich finde ein shared_ptr macht insbesondere dann sinn, wenn eine ressource von mehreren threads verwendet wird. wer soll die ressource denn freigeben, wenn die threads fertig sind?

    ja, hier sehe ich sie auch voll ein. also naja, oft halt. sachen wie der http-server, wo jeder worker-thread genau einen socket hat und nur der server-thread alle sockets erzeugt hat, zählen hier natürlich nicht. muss schon mehr datenchaos sein, wo man gar nicht mehr nachvollziehen kann, wer was erzeugt hat und wer was kennt.

    aber nicht immer dieses gesabble, daß man gleich jeden vector<Foo*> durch einen vector<shared_ptr<Foo> > ersetzen sollte, weil es angeblich durchschaubarer und schneller sei, nicht mehr den besitzenden container löschen zu lassen, sondern die zeigerchen selber damit beauftragt.



  • ness schrieb:

    @Kingruedi: Das klingt ja interessant. Alle pointer durch einfache smart-pointer ersetzen, die einem im debugmodus Überprüfungsmöglichkeiten bieten. Könntest du das pointer Klassentemplate im Ansatz mal zeigen? Ich meine wie prüft man einen pointer auf seine gültigkeit, außer auf Null?

    template<typename T>
    class ptr {
      T *p;
    public:
      typedef T value_type;
    
      ptr(value_type *o=0x0) : p(o) { }
    
      value_type &operator*() {
        assert(p);
        return *p;
      }
      //...
    };
    

    Überprüfungsmöglichkeiten hängen von deinem OS ab.



  • kingruedi schrieb:

    ness schrieb:

    @Kingruedi: Das klingt ja interessant. Alle pointer durch einfache smart-pointer ersetzen, die einem im debugmodus Überprüfungsmöglichkeiten bieten. Könntest du das pointer Klassentemplate im Ansatz mal zeigen? Ich meine wie prüft man einen pointer auf seine gültigkeit, außer auf Null?

    template<typename T>
    class ptr {
      T *p;
    public:
      typedef T value_type;
    
      ptr(value_type *o=0x0) : p(o) { }
    
      value_type &operator*() {
        assert(p);
        return *p;
      }
      //...
    };
    

    Überprüfungsmöglichkeiten hängen von deinem OS ab.

    lol. irgendwie brings das assert in operator* nicht. Man kann das doch einmal im Konstruktor überprüfen und dann kann sich doch eh nichts mehr ändern.



  • Und wenn der Zeiger "von außen" verändert wird...



  • Helium schrieb:

    Naja, durch Smartpointer kommen 99% aller Klasse ohne selbstgeschriebenen Destruktor aus. Das heißt man muss nurnoch Copy-C'tor und operator = implementieren oder ein NO_COPY-Makro einbauen.
    Von wegen "Regel der großen Drei". 👎

    👍 für das Leben ohne Destruktoren. Aber warum NO_COPY? Wenn du scoped_ptr<> benutzt, hast du standardmäßig keine Kopiermöglichkeit mehr.

    Und für häufige Aufgaben des CCtor/op= kann man sich dann noch einen eigenen SmartPtr schreiben (z.B. einen CopyPtr, der im CCtor/op= seinen Pointee über den CCtor klont) und sich sogar CCtor und op= sparen, weil die compilergenerierten genau das Richtige tun.



  • volkard schrieb:

    wenn ich nur auf *ein* objekt zeige, das mir auch noch gehört (also für dessten destruktion ich zuständig bin), dann sollte das objekt einfach member meiner klasse sein, und kein zeiger auf's objekt.

    Also mal von Objekten abgesehen, die es nur manchmal geben muss, scheitert diese schöne Theorie bei mir oft an der Praxis. Was ein Member der Klasse ist, muss nämlich auch in der unsäglichen Initialisierungsliste erstellt werden, und da kann man nicht so einfach Konstruktorargumente der Member erstmal zusammenbauen und dann die Member daraus erstellen (z.B. erstmal einen Dateinamen lowercasen, umdrehen und dann ".dat" anhängen).

    Oder um es mal mit einem gar nicht so dahergeholten Beispiel zu erklären:

    struct Bitmap { /* teuer zu kopieren, oder noch besser gar nicht */ };
    struct D3DTexture { D3DTexture(const Bitmap& bmp); };
    
    struct D3DText
    {
        boost::scoped_ptr<D3DTexture> tex;
    
        D3DText(string str)
        {
            Bitmap bmp;
            bmp.resize(100, 100);
            bmp.drawText(str, 0, 0);
            tex.reset(new D3DTexture(bmp));
        }
    };
    

    Das Problem ist hier einfach, dass man Member nicht erst später im Konstruktor erstellen darf (über "init tex(bmp)" in diesem Beispiel). C++ doof.



  • operator void schrieb:

    👍 für das Leben ohne Destruktoren. Aber warum NO_COPY? Wenn du scoped_ptr<> benutzt, hast du standardmäßig keine Kopiermöglichkeit mehr.

    das meinste nicht ernst, oder?

    soll ich also klassen schreiben, die bei
    Foo a;
    Foo b=a;
    undefiniert sind, nur weil es nicht zu problemen kommt, wenn ich diese dinge mit scoped_ptr anfasse?
    klingt mir nach grobem unfug. ich mache NO_COPY, weil die klassen nicht sinnvoll kopiert werden können. und dabei achte ich nicht drauf, ob sie zufällig fehlerfrei kopierbar sind, sondern ob es inhaltlich sinn macht, sie zu kopierbar zu machen.



  • operator void schrieb:

    Also mal von Objekten abgesehen, die es nur manchmal geben muss, scheitert diese schöne Theorie bei mir oft an der Praxis.

    bei mir nicht.

    Was ein Member der Klasse ist, muss nämlich auch in der unsäglichen Initialisierungsliste erstellt werden, und da kann man nicht so einfach Konstruktorargumente der Member erstmal zusammenbauen und dann die Member daraus erstellen (z.B. erstmal einen Dateinamen lowercasen, umdrehen und dann ".dat" anhängen).

    ?

    struct Bitmap { /* teuer zu kopieren, oder noch besser gar nicht */ };
    struct D3DTexture { D3DTexture(const Bitmap& bmp); };
    
    struct D3DText
    {
        boost::scoped_ptr<D3DTexture> tex;
    
        D3DText(string str)
        {
            Bitmap bmp;
            bmp.resize(100, 100);
            bmp.drawText(str, 0, 0);
            tex.reset(new D3DTexture(bmp));
        }
    };
    

    mhmm. würde sowas helfen?

    #include <string>
    #include <iostream>
    using namespace std;
    
    class NoCopy{
    private:
    	NoCopy(NoCopy const&);
    	NoCopy& operator=(NoCopy const&);
    public:
    	NoCopy(){
    	}
    };
    
    #define NOCOPY NoCopy _noCopy
    
    class Bitmap{ // teuer zu kopieren, oder noch besser gar nicht
    	NOCOPY;
    public:
    	Bitmap(){
    	}
    	void resize(size_t nx,size_t ny){
    	}
    	void drawText(string const& str,size_t x,size_t y){
    	}
    };
    struct D3DTexture { 
    	NOCOPY;
    	D3DTexture(const Bitmap& bmp){
    	}
    };
    
    struct D3DText
    {
        D3DTexture tex;
    
    	Bitmap const& strangeFoo(string const& str,Bitmap const& cbmp=Bitmap()){
    		Bitmap& bmp=const_cast<Bitmap&>(cbmp);
            bmp.resize(100, 100);
            bmp.drawText(str, 0, 0);
    		return bmp;
    	}
    
        D3DText(string str)
    	:tex(strangeFoo(str)){
        }
    };
    
    int main(){
    	D3DText("hello");
    }
    

    ?
    liegt mir irgendwie mehr.

    Das Problem ist hier einfach, dass man Member nicht erst später im Konstruktor erstellen darf (über "init tex(bmp)" in diesem Beispiel). C++ doof.

    jo, c++ ist doof.



  • volkard schrieb:

    Das Problem ist hier einfach, dass man Member nicht erst später im Konstruktor erstellen darf (über "init tex(bmp)" in diesem Beispiel). C++ doof.

    jo, c++ ist doof.

    [flamemode]
    wieso benutzt ihr es dann?
    [/Flamemode]



  • ⚠ nesting error: the tag 'Flamemode' is closed without having been opened previously.
    ⚠ the tag 'flamemode' was not closed proberly.



  • otze schrieb:

    volkard schrieb:

    Das Problem ist hier einfach, dass man Member nicht erst später im Konstruktor erstellen darf (über "init tex(bmp)" in diesem Beispiel). C++ doof.

    jo, c++ ist doof.

    [flamemode]
    wieso benutzt ihr es dann?
    [/Flamemode]

    Weil es nichts besseres gibt?



  • Optimizer schrieb:

    ⚠ nesting error: the tag 'Flamemode' is closed without having been opened previously.
    ⚠ the tag 'flamemode' was not closed proberly.

    *g*



  • Optimizer schrieb:

    ⚠ nesting error: the tag 'Flamemode' is closed without having been opened previously.
    ⚠ the tag 'flamemode' was not closed proberly.

    [CaseSensitivity="Off"]
    [FlAmEmOdE]
    ich hasse dich
    [/fLaMEmODe]
    [CaseSensitivity="on"]



  • kiddies, es reicht langsam.



  • Was haltet ihr von Boost?

    Taugt Boost auch für prof. Anwendungen,

    Noch nicht, da kein Standard und auch noch nicht klar ist, was eventuell übernommen wird.

    oder ist das mehr eine akademische Spielwiese?

    Yep.
    😉



  • volkard: müßte strangeFoo nicht legalerweise static sein? (wg. D3DText-member noch nicht initialisiert) Ist aber ne nette Idee.

    Was ich noch nicht verstehe: Wie "merkt" sich D3DTexture das Bitmap?
    mekt sich's ne Referenz, dann get die referenz doch auf ein temporary. Und kopieren kann er's ja auch nicht??!



  • peterchen schrieb:

    volkard: müßte strangeFoo nicht legalerweise static sein?

    jo, auf jeden fall static.

    Was ich noch nicht verstehe: Wie "merkt" sich D3DTexture das Bitmap?
    mekt sich's ne Referenz, dann get die referenz doch auf ein temporary. Und kopieren kann er's ja auch nicht??!

    weiß ich auch nicht. hab nur die vorgabe umgemodelt.


Anmelden zum Antworten