factory + smart pointer



  • Wäre es trotzdem nicht besser nen rohen Zeiger zurückzugeben und den Clienten entscheiden zu lassen, wo er ihn reinpacken will.
    Intern kann man selbst schön mit smart Pointern arbeiten, aber nach außen sollte man einen "reinen" Typen zurückgeben, denn nicht jeder hat boost installiert.

    So zwingst du ja den Benutzer deiner Library auch die installation von boost. In einigen Fällen ist das zwar gut, aber bei kleinen Librarys würde ich sowas versuchen zu vermeiden.



  • asc schrieb:

    Nein, ist es nicht. Nicht so wie du es anwendest.

    doch, ist es. tachyons einwand war auf die nackten pointer bezogen, nicht auf die shared_ptr.

    Shade Of Mine schrieb:

    fabrikarbeiter schrieb:

    hallo

    Shade Of Mine schrieb:

    warum nicht einfach einen normalen zeiger zurueck geben?

    weil ein shared_ptr für meine situation sehr gut passen und das interface vereinfachen würde.

    Und ich dachte der Thread geht darueber dass shared_ptr eben nicht passt weil es damit keine covariant return types gibt.

    ähm ja, genau darum geht es. ein shared_ptr würde vom prinzip her für meine situation sehr gut passen und das interface vereinfachen - wenn das problem mit der fehlenden covarianz nicht wäre.

    asc schrieb:

    Der Sinn einer solchen Fabrik ist aber das der Typ nicht entscheidend ist (Polymorphie) - sprich eigentlich wäre die Rückgabe von boost::shared_ptr<base> richtig.

    das ist mir bewusst. ich brauche an dieser stelle aber die spezialisierung. base gibt die schnittstelle vor, die nach außen hin relevant ist.
    derived implementiert aber plattformspezifische details in form von zusätzlichen funktionen, die sich in base nicht sinnvoll unterbringen lassen. deshalb brauche ich intern ein derived, außerhalb aber nur ein base.

    Shade Of Mine schrieb:

    in den meisten faellen ist scoped_ptr einfach besser.

    aber der löst auch nicht rein zufällig mein covarianz-problem, oder?



  • KasF schrieb:

    Wäre es trotzdem nicht besser nen rohen Zeiger zurückzugeben und den Clienten entscheiden zu lassen, wo er ihn reinpacken will.

    Gut, dann wiederhole ich meine Ernst gemeinte Frage:

    Don06 schrieb:

    Wie würdest du das Problem der flexiblen Freigabe lösen? Eine Methode, die das Objekt selbst zerstört (delete this; / free(this); / ...) oder eine freie Funktion (gut, ist jetzt nicht so der große Unterschied)? Oder ganz anders?



  • Shade Of Mine schrieb:

    ein shared_ptr macht auch nur ein delete.
    smart pointer haben keine magie dabei...

    Nicht "auch nur ein delete", sondern eine Zusicherung: Es wird ein delete durchgeführt. Den bei den normalen Zeigern ist es nicht sicher das ein delete beabsichtigt ist!

    Shade Of Mine schrieb:

    ich sehe keinen vorteil darin shared_ptr aus einer factory methode zu liefern. denn das schoene an zeigern ist, dass ich sie jederzeit in einen smart pointer packen kann - und shared_ptr ist der 2. teuerste smart pointer den es gibt. wenn man ihn braucht sind die kosten egal, aber wozu ueberall einsetzen?

    Um sicherzustellen das die richtige Freigabestrategie gewählt wird, unabhängig davon wie es hinter der Schnittstelle aussieht. Du hast recht das der shared_ptr teuer ist, aber ich Optimiere nicht im voraus, wenn ein Profiler mir sicher sagen kann, das es hier ein Problem in meinen Programm gibt, kann ich immer noch nach alternativen suchen!

    Shade Of Mine schrieb:

    in den meisten faellen ist scoped_ptr einfach besser.

    Er schließt die Verwendung in Listen etc. aus. Ich ziehe den scoped_ptr für Daten vor, wo ich wirklich garantieren kann das sie Scopebezogen gelten.

    Shade Of Mine schrieb:

    vorallem ist das ganze hier ein super beispiel warum smart pointer nicht immer die beste wahl sind. man kann natuerlich sagen: ok, dann verzichte ich auch covriant return types - aber ist das nicht eher eine entscheidung die der client code treffen sollte und nicht der provider code?

    Dann würde ich die Factory aber eindeutig steuern (z.B. über Policyklassen), damit GARANTIERT ist was dort zurückgegeben wird.

    Shade Of Mine schrieb:

    denn es bringt keine abstraktion oder sonstige vorteile fuer die factory wenn sie direkt einen smart pointer liefert. es ist aber manchmal fuer den client unpraktisch. und smartpointer kann man so oder so verwenden.

    Es gibt einen ganz gewaltigen Vorteil den ich aber auch schon erwähnt hatte: Eine Garantie der Freigabestrategie.



  • Don06 schrieb:

    KasF schrieb:

    Wäre es trotzdem nicht besser nen rohen Zeiger zurückzugeben und den Clienten entscheiden zu lassen, wo er ihn reinpacken will.

    Gut, dann wiederhole ich meine Ernst gemeinte Frage:

    Don06 schrieb:

    Wie würdest du das Problem der flexiblen Freigabe lösen? Eine Methode, die das Objekt selbst zerstört (delete this; / free(this); / ...) oder eine freie Funktion (gut, ist jetzt nicht so der große Unterschied)? Oder ganz anders?

    Ich würde es bei meiner Library anders lösen, nämlich einen eigenen smart_ptr bereitstellen 😉 Somit würde ich den User aufzwingen den smart_ptr meiner Lib zu benutzen um so die benutzung von boost zu vermeiden.

    Es ist ja ehe nicht das gelbe vom Ei nen rohen Zeiger so zurückzugeben und das weiß vermutlich auch jeder anständige C++ Programmierer, denn niemand weiß woher der Zeiger kommt und wie dafür Speicher alloziert wurde und eigene Funktion der Lib dann bereitzustellen die das Löschen übernehmen, finde ich auch ziemlich eklig.

    Also fabrikarbeiter, schreib die deinen eigenen smart_ptr. Das Verhalten zu erziehlen einen smart_ptr<Derivied> in smart_ptr<Base> konvertieren zu lassen ist auch ganz einfach 😉



  • Wer sagt denn, das man boost braucht? shared_ptr gibts im TR1.



  • HansiHinterseher schrieb:

    Wer sagt denn, das man boost braucht? shared_ptr gibts im TR1.

    Stimmt.
    Aber leider hat momentan nicht jeder einen Compiler der TR1 bereitstellt und solange müssen die Leute auf boost::tr1 zurückgreifen.



  • ich bin nicht der meinung, dass der client selber entscheiden können sollte ob er einen schlauen oder einen dummen pointer will. wenn die factory smartpointer zurückliefert, dann sichert man damit ein bestimmtes verhalten zu.

    dumme pointer könnten z.b. einfach gelöscht werden, obwohl es an anderen stellen noch x referenzen auf das dahinter liegende objekt gibt. der client weiß einfach nicht, wie lange das objekt gültig bleibt. oder ob, wann und wie er es löschen darf, soll oder muss. wenn ich meine bisherigen erfahrungen so betrachte, ist das eine typische fehlerursache.

    mit einem smartpointer ist es klar: der letzte macht das licht aus und der provider entscheidet, wie der lichtschalter aussieht. das ist genau das, was ich meistens will.

    dass smartpointer evtl. mehr performance kosten, spielt an dieser stelle eigentlich gar keine rolle. die objekte werden ja nicht in einer tour erzeugt und wieder zerstört.

    @tachyon: wo genau liegt denn die problemlösung bei deinem workaround? ich verstehe nicht, worauf du hinaus willst. dein code hat das gleiche problem hat wie meiner (base_factory::create() und derived_factory::create() mit nicht kovarianten rückgabetypen).

    dass die verwendung von boost als nachteil gewertet wird, ist in diesem fall echt lustig. ich habe mich nach jahrelanger weigerung dazu entschieden, boost dieses mal eine chance zu geben, statt das rad immer wieder neu zu erfinden. und schon beim ersten problem kommt der vorschlag, es doch lieber selbst zu programmieren 🙂



  • fabrikarbeiter schrieb:

    dass die verwendung von boost als nachteil gewertet wird, ist in diesem fall echt lustig.

    Find ich eher traurig. Boost ist zu einem nicht kleinen Teil von Leuten die im C++ Standardkomitee sitzen beeinflusst wurden. Ich behaupte mal das boost zu den besten C++ Bibliothekssammlungen überhaupt zählt.

    Wenn ich mit Strings arbeite verwende ich auch nicht char* sondern std::string, und schreibe keine eigene Umsetzung.

    Ich verstehe hier eh nicht warum sich die Leute hier wegen Performance und Overhead aufregen. Wozu gibt es Profiler, wozu gibt es Refactoring, und wo ist bitte die Sicherheit bei dem Ganzen.

    Vorzeitige Optimierung ist die Wurzel allen Übels. Warum nicht erst einmal sicheren Code schreiben und dann später die Teile anpassen die tatsächlich ein Flaschenhals in der Anwendung sind. Ich habe inzwischen die Erfahrung in meinen Programmen gemacht, das obwohl ich intensiv mit Smartpointern und ähnlichen Technologien arbeite meine Programme schnell sind. Okay, das liegt natürlich auch an den Anwendungsbereichen. Wenn ich innerhalb kürzester Zeit Abertausende Objekte anlegen muss gibt es besseres - wobei dort dann auch die Frage ist ob nicht replacement new verwendet wird, oder ganz andere Speicherverwaltungsregeln gelten sollten (und spätestens bei Zweiten können nackte Zeiger auch wieder problematisch sein).

    cu André



  • asc schrieb:

    ...

    Da bin ich absolut deiner Meinung.Meist liegt ein Performanceeinbruch eh nicht dort, wo man am Anfang erst vermuten würde und es ist schlussendlich viel ineffizienter, wenn du durch vorranige Suche und kopfzerbrechen etwas machst, was schlussendlich eh nicht mehr draufankommt, sondern ein völlig anderer Teil Probleme macht.



  • Wer meint, Smartpointer machen "auch nur ein delete", dem sei dieser Artikel ans Herz gelegt:
    http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html

    Mit Shared Pointern kann man theoretisch z.B. full-featured Connectionpooling implementieren. Da ist es aber wenig hilfreich, wenn man dem Aufrufer die Wahl der Verwaltung/Zerstörung überlässt.



  • asc schrieb:

    Ich verstehe hier eh nicht warum sich die Leute hier wegen Performance und Overhead aufregen. Wozu gibt es Profiler, wozu gibt es Refactoring, und wo ist bitte die Sicherheit bei dem Ganzen.

    Wenn du damit micht meinst, ich habe nie das Wort Performance erwähnt oder sonstiges in der Richtung.

    Mir gehts nur darum, dass der arme Benutzer der Lib sich nicht extra zusätzlich boost draufmachen muss. Bei einer kleinen Lib fänd ichs ziemlich lästig, aber es hängt auch von der Zielgruppe ab.

    Der Entwickler kann das wohl am besten entscheiden. Wenn es aber keine Lib wird und es um ein eigenes Projekt geht, dann spricht rein gar nichts gegen boost 😉


Anmelden zum Antworten