Temporäre Variablen gekapselt in welchem boost_ptr?



  • Hi,

    ich habe einige Funktionen, die temporäre Daten anlegen, welche vom Aufrufer genutzt werden sollen und dann automatisch gelöscht werden sollen. Klingt also nach einem perfekten Einsatz für einen smart_ptr.

    Wie mache ich das jetzt geschickt? Ich könnte die Daten direkt in einem shared_ptr zurückgeben, aber shared_ptr sind teuer, richtig? Außerdem brauche ich das Objekt nur an einer Stelle: dort, wo der Aufrufer die Daten nutzt.

    Alternative wäre, wenn ich nur einen normalen Pointer zurückliefere und der Benutzer sich selbst darum kümmern muss, dass delete aufgerufen wird bzw. er das in den Smartptr packt. Das finde ich aber nicht sehr programmier-freundlich, weil der Benutzer immer aufpassen muss...

    Gibt es noch eine elegantere Lösung oder findet ihr einen shared_ptr dafür schon ok?



  • Einen std::unique_ptr, falls du C++0x nutzt. 😉



  • Nutz ich schon, aber ich habe in dem Projekt gerade sowieso boost-ptr im Einsatz und irgendwie find ich C++0x-ptr mit boost-ptr mischen jetzt nicht sooo toll. Ich meine, wenn beides gleich gut klappt und ich schon boost-ptr nutze ist es doch für den Benutzer verwirrend, wenn ich hier boost-ptr und da 0x-ptr nutze...

    Oder gibt es boost nichts für meine Zwecke?



  • Ich würde auch unique_ptr benutzen. Damit machst du dem Aufrufer klar, dass das Objekt übertragen wird und immer nur einen Besitzer hat. Bei shared_ptr kann es grundsätzlich sein, dass sonst noch wer eine Referenz auf das Objekt hält und die Freigabe verhindert. Zudem fällt der ganze Overhead mit Reference Counting, Threadsicherheit, Custom Deleter etc. weg. Falls nötig kann ja der Benutzer selbst immer noch einen shared_ptr verwenden. In Zukunft wird Boost vielleicht sogar eine implizite Konvertierung anbieten, für den Fall, dass C++0x verwendet wird.

    Siehe auch hier.



  • Die "Kosten" eines shared_ptr werden in meinen Augen überbewertet, es ist ja nicht so, dass du tausende davon erzeugst und wieder zerstörst (oder doch? Wie häufig ereignet sich der Fall, für den du das Objekt brauchst?). Wenn man weiß, dass man ein Problem performancekritisch lösen muss sollte man sich natürlich Gedanken über zusätzlichen Overhead machen, aber in 99% aller Fälle spielt der Overhead eines shread_ptr gegenüber einem unique_ptr nicht in´s Gewicht. Wenn du unique_ptr also nicht benutzen kannst oder willst spricht nichts gegen die Verwendung von shared_ptr, oder von mir aus auch einem temporären scoped_ptr



  • Okay, aber dann wäre das der Verständlichkeit ja nicht so abträglich, da unique_ptr und shared_ptr offensichtlich andere Anwendungsbereiche haben.

    Wie nutze ich denn scoped_ptr ohne das Problem, dass der Benutzer das selbstständig in einen scoper_ptr packen muss? Ich meine, Benutzer weiß erstmal nicht, dass er dafür verantwortlich ist das Zurückgegebene wieder zu löschen, daher wollte ich ja die direkte Ummantelung.



  • Wie nutze ich denn scoped_ptr ohne das Problem, dass der Benutzer das selbstständig in einen scoper_ptr packen muss? Ich meine, Benutzer weiß erstmal nicht, dass er dafür verantwortlich ist das Zurückgegebene wieder zu löschen, daher wollte ich ja die direkte Ummantelung.

    Bevor du dem Nutzer Speicherverwaltung aufbürdest, nimm lieber nen shared_ptr.


  • Mod

    Wieso überhaupt dynamische Speicheranforderung und nicht eine normale Rückgabe, wenn das Ganze ohnehin vom Aufrufer direkt konsumiert werden soll?



  • Hm, gute Frage. Weil mir die Kopie zu teuer ist? Oder wird das mit 100%ger Sicherheit wegoptimiert?



  • Eisflamme schrieb:

    Hm, gute Frage. Weil mir die Kopie zu teuer ist? Oder wird das mit 100%ger Sicherheit wegoptimiert?

    Teure Kopien lassen sich oft durch Move-Semantiken lösen. 🙂


  • Mod

    Eisflamme schrieb:

    Hm, gute Frage. Weil mir die Kopie zu teuer ist? Oder wird das mit 100%ger Sicherheit wegoptimiert?

    Mit jedem hinreichend modernen Compiler: ja. Die Eliminierung von temporären Objekten ist immer möglich, bei benannten Objekten geht es immer dann, wenn bestimmte Voraussetzungen erfüllt sind:
    NRVO ist für ein bestimmtes benanntes Objekt dann möglich, wenn sich innerhalb des potentiellen Scopes dieses Objektes keine return-Anweisung findet, die nicht dieses Objekt zurückgibt. NRVO wird in der Regel für Funktionsparameter nicht unterstützt (abgesehen von inlining).


  • Mod

    Ethon schrieb:

    Eisflamme schrieb:

    Hm, gute Frage. Weil mir die Kopie zu teuer ist? Oder wird das mit 100%ger Sicherheit wegoptimiert?

    Teure Kopien lassen sich oft durch Move-Semantiken lösen. 🙂

    Move ist in der Regel nur dann wesentlich billger als Kopieren, wenn das Objekt selbst nur Verweise auf Resourcen enthält, also im Prinzip nur (Smart-)pointer hält. Damit wären wir wieder am Ausgangspunkt der Diskussion.



  • camper schrieb:

    Ethon schrieb:

    Eisflamme schrieb:

    Hm, gute Frage. Weil mir die Kopie zu teuer ist? Oder wird das mit 100%ger Sicherheit wegoptimiert?

    Teure Kopien lassen sich oft durch Move-Semantiken lösen. 🙂

    Move ist in der Regel nur dann wesentlich billger als Kopieren, wenn das Objekt selbst nur Verweise auf Resourcen enthält, also im Prinzip nur (Smart-)pointer hält. Damit wären wir wieder am Ausgangspunkt der Diskussion.

    Aber das ist in der Realität praktisch das einzige Szenario, bei dem Kopieren teuer ist.
    Meistens sind es doch Strings, Vektoren, Handles etc.



  • Soweit ich weiß greift die Move-Semantik hier überhaupt nicht oder irre ich? Wenn NRVO aber immer klappt, ist das ok.


Log in to reply