Was taugt Boost?
-
Lars Hupel schrieb:
ich brauche dringend thread
jetzt mal für alle windows-user, die es nicht schaffen die index.html zu lesen:
1. <Boost>\tools\build\jam_src\build.bat
starten. das script startet dann den compiler über die Registry.2. nach <Boost> wechseln und
bjam "-sTools=COMPILER" install
ausführenCompiler-Kürzel:
Compiler - Kürzel - Beschreibung vc7 vc MS Visual C++ command-line tools from VisualStudioNET. vc7-stlport vc MS Visual C++ cmd-line tools from Visual Studio .NET+STLPort. vc-7_1 vc Visual C++ command-line tools from Visual Studio .NET 2003. vc-7_1-stlport vc Microsoft Visual C++ command-line tools from Visual Studio .NET 2003 + STLPort.
- ungetestet -
mfg
-
peterchen schrieb:
m.E. gwehören Smart Pointer zum handwerkszeug jedes "ordentlichen" C++ - Programmierers, weil man sich viele Ressourcenprobleme sparen kann.
ganz deiner meinung.
* Funktionen/Methoden die (komplexe) Objete erstellen.
Das Objekt wird ohne teure Kopie zum retval, kann also direkt weitergegeben werden, und der Erzeuger packt gleich die Anleitung dazu, wie das Objekt freizugeben ist.sieht nach auto_ptr aus.
achn nur wegen performance? warum glaubste nicht an RVO?bei
CFoo * GetFoo()
muß man dokumentieren und sich Gedanken machen wer den Zeiger wann freigbt.
der macht frei, der angelegt hat? oder zur makeFoo die entsprechende destroyFoo.
* Implementation von Copy-On-Write
tritt seltener auf, ist geht aber mit einem ordentlichen smart pointer in der tasche hinreichend simpel.naja, echt selten.
* Entkopplung von Objekten
Objekt A braucht temporär ein Objekt B als State und will sich nicht drum scheren, ob und wann es B freigeben soll.temporäre variablen liegen auf dem heap.
für enbtkopplung ala pimpl gibts besseres.
-
Ich hab mich sowieso schon immer gefragt, warum man für dieses pimpl idiom einen smart pointer braucht, wos doch auch ein normaler tut.
-
weil ich sie nicht oder nur exrem selten brauche. ich habe keinen bedarf. ich weiß nicht, warum andere leute bedarf haben. ich schaue leute, die dauernd shared_ptr verwenden, genauso schief an, wie leute, die dauernd dynamic_cast oder switch verwenden.
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".Ich bin sowieso jemand, der in der Richtung sehr extrem ist. Sowas, wie "close" oder ähnliches existiert bei mir eigentlich gar nicht mehr. Bei mir geht alles über RAII. Ich komme damit wunderbar klar, habe bisher keine Geschwindigkeitsprobleme gehabt, bin eigentlich immer Exceptionsicher und muss mich niemals ums freigeben kümmern.
Zurück zur eigentliche Frage. Boost ist keine Spielerei. Ohne Boost käme ich gar nicht mehr aus. Bei mir geibt es immer öfter boost::function und boost::bind. Einfach genial und inzwischen bei mir unverzichtbar.
-
peterchen schrieb:
* Funktionen/Methoden die (komplexe) Objete erstellen.
Das Objekt wird ohne teure Kopie zum retval, kann also direkt weitergegeben werden, und der Erzeuger packt gleich die Anleitung dazu, wie das Objekt freizugeben ist.
beiCFoo * GetFoo()
muß man dokumentieren und sich Gedanken machen wer den Zeiger wann freigbt.
Kommste auch ohne Boost aus, hier kann dir auto_ptr<> helfen. Ist sogar in den meisten Fällen sinnvoller als smart_ptr, wie ich finde. Außer man hat eine Factory, dann ist natürlich smart_ptr für den User komfortabler.
Bei öffentlichen Schnittstellen vermeide ich aber prinzipiell native Pointer. Nur bei privaten Methoden, wo ich weiß was passiert, sind native Pointer schon mal zu sehen.
-
Stimmt, viele Sachen kann man auch anders lösen, auch effektiver.
Mein Gedanke ist: Smart Pointer braucht man sowieso. Wenn man sie also "fleißig" benutzt, ist man an ein paar Stellen vielleicht nicht so effektiv, aber hat insgesamt eine weniger komplexe Lösung.
Das folgende also nur warum *ich* an den gegebenen Stellen einen smart pointer bevorzuge (ob boost oder loki oder sonstwer ist mir fast egal, aber boost mag ich halt)
auto_ptr ist mein ganz persönlicher Feind. Löst zwar in den meisten Fällen das Problem genausogut, nur sind die Fälle schwieriger festzustellen, man muß ständig die Ownership im Hinterkopf behalten, es gibt immer eine "besondere" auto_ptr-Variable.
ein separates destroyFoo will ich ja gerade vermeiden - der Client soll nicht mehr darüber nachdenken müssen, wo er den Zeiger herbekommt. Die Flexibilität einer create/destroy - Schnittstelle bekommst du auch mit einem custom deleter hin. Das ist besonders nett, wenn du zwischen mehreren Factories wählen kannst / mußt. (gibt's nicht? hast du einen HDC, mußt du DeleteDC, ReleaseDC oder gar nix machen?)
Für PIMPL würd ich scoped_ptr verwenden :=)
Natürlich kümmert der sich "nur" um das eine kleine delete. Aber am Tagesende fragt mich mein Chef nicht, ob ich an alle deletes gedacht habe, sondern ob die Kurve schon krumm und bunt ist. Jede Sache die ich vergessen kann ist mir also recht.Bei "Entkoppelung" denk ich an so simple Dinge wie: welchen Font verwendet mein Control heute zum Zeichnen. Ist eine Eigenschaft des Controls, soll der Client jederzeit ändern können. Natürlich darf der auf dem Heap liegen - aber vielleicht ja grad mal nicht? Oder kommt aus einer anderen Bibliothek die sich selbst drum kümmert? Mit einem guten Smart Pointer kann man dicht an der "schmalsten Brücke" bleiben, kann aber hat aberweniger zu beachten.
RVO: ist leider nicht garantiert.
-
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.
naja, 99% der klassen kommen auch so schon ohne selbstgeschriebenen dtor aus, dachte ich. weil wir ja rohe zeiger entweder brauchen, um arrays zu machen (machen wir aber besser mit std::vector oder ähnlichem) oder zum pimpln (machen wir auch besser anders) (außerdem inst pimpln nur detail, um zur compilezeit was zu sparen). 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.
und NO_COPY verwende ich eh echt viel.
Ich bin sowieso jemand, der in der Richtung sehr extrem ist.
ich auch.
sowas wie close exisiert bi mir nicht mehr
bei mir auch nicht. ist ein weiterer punkt, weshalb members nicht mehr zeiger sein mössen. notwendig ist natürlich, daß ein ctor, der nicht klappt, auch fein eine exception wirft.
Bei mir geht alles über RAII. Ich komme damit wunderbar klar, habe bisher keine Geschwindigkeitsprobleme gehabt, bin eigentlich immer Exceptionsicher und muss mich niemals ums freigeben kümmern.
java-user haben auch eigentlich nir geschwindigkeitsprobleme und müssen sich niemals ums freigeben kümmern.
kannst du mir ein beispiel nennen, wo shard_ptr (oder verwendest du da auto_ptr?) sehr praktisch ist und dir nen dtor spart, und wo du zugleich "eine klasse, ein zweck" verfolgt hast?
-
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?
Gruß mathik
-
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]