Designfrage - Menge als Rückgabewert



  • otze schrieb:

    Auch ist die Datenmenge groß genug, dass ich es mir mehrmals überlegen würde, sie zu kopieren, also fällt ein Container als Rückgabewert raus.

    Dafür gibt's die "Return Value Optimization". Der MSVC kann's, der g++ laut kurzer Google-Nachfrage seit Version 3.1. Zum Lesen:
    http://msdn.microsoft.com/en-us/library/ms364057%28VS.80%29.aspx



  • @Badestrand: dein Link beschreibt die NRVO. RVO != NRVO. Und RVO würde in diesem Fall auch vermutlich garnix bringen.

    @otze: bist du sicher dass das Kopieren der Liste, im Vergleich mit dem Analysieren des Bildes, überhaupt lange dauert? Wenn das bloss ein paar Prozent sind, dann ... -> wurscht



  • hustbaer schrieb:

    @Badestrand: dein Link beschreibt die NRVO. RVO != NRVO. Und RVO würde in diesem Fall auch vermutlich garnix bringen.

    Upsi, da hab ich was durcheinandergeworfen. Aber wie wär's mit 'nem aktuellen Compiler, greift bei Objekt-Rückgabe nicht die Move-Semantik?



  • @ audacia: scoped_ptr ist nicht kopierbar (und zudem nicht in TR1).

    Was du wahrscheinlich meinst, ist std::auto_ptr .



  • Nexus schrieb:

    @ audacia: scoped_ptr ist nicht kopierbar (und zudem nicht in TR1).

    Tatsächlich - das war ein Flüchtigkeitsfehler; ich meinte natürlich shared_ptr<> . Danke für den Hinweis.



  • Badestrand schrieb:

    hustbaer schrieb:

    @Badestrand: dein Link beschreibt die NRVO. RVO != NRVO. Und RVO würde in diesem Fall auch vermutlich garnix bringen.

    Upsi, da hab ich was durcheinandergeworfen. Aber wie wär's mit 'nem aktuellen Compiler, greift bei Objekt-Rückgabe nicht die Move-Semantik?

    Nur wenn die Klasse die als Return-Typ verwendet wird move-semantics unterstützt. Was die std:: Container tun sollten (und in der STD-Lib vom 2010 Beta auch implementiert ist -- GCC weiss ich nicht, vermutlich auch).

    Ich denke das wäre eine gute Möglichkeit: sich drauf verlassen dass es eh egal ist, und sobald man einen Compiler hat der r-value refs kann, fällt der (vermutlich minimale) Overhead dann auch noch weg.

    Falls man wirklich draufkommt, dass es nicht egal ist, kann man sich immernoch über diverse Workarounds ein "move-by-swap" für die Standard-Container basteln. Siehe boost::move_t<>.



  • Andere Möglichkeit wäre, den Container auf dem Heap zu erzeugen und einen Proxy zu schreiben, der die ganzen Implementierungsdetails (was für ein Container es wirklich ist usw.) kapselt. Schreib ein Interface, das den Ansprüchen der Clients genügt und implementiere es so, dass es den Performanceansprüchen genügt (move-Semantik usw.)



  • BTW:

    Wenn der Container nur als Ausgabe verwendet würde, d.h. die Funktion da nur reinschreiben muss, dann wäre die Standard-Lösung natürlich nen Output-Iterator zu verwenden.

    Wenn die Funktion wirklich den Container braucht, z.B. um nachsehen zu können ob es schon einen Eintrag gibt, dann würde man mit der Output-Iterator Variante natürlich wieder sinnlos Daten kopieren. Ist aber IMO wirklich die Frage ob das nicht egal ist. Vor allem da es dann eine sehr saubere Trennung gäbe.

    ----

    Oder ... ganz doofer Vorschlag:
    Du könntest die Funktion als Input-Iterator implementieren (mit lazy evaluation, oder auch ohne) 😃



  • Vielleicht wäre auch std::auto_ptr eine Möglichkeit, Move-Semantik zu erzeugen. Eventuell reicht das ja.



  • Erstmal Danke für die Antworten. Ich habe leider immer noch keinen Favoriten rauspicken können. Der OutputIterator wäre sicherlich noch eine Idee die zumindest bei einigen Modulen für eine Verbesserung sorgen könnte. Andere wiederum speichern den Container auch intern um ihn zwischen den Aufrufen nur anzupassen, allerdings sollte in diesen Bereichen eigentlich die Datenmenge recht gering sein. Ich denke, ich werde das mal in der Gruppe ansprechen. Bislang sind wir mit dem Design noch nicht wirklich zufrieden 😉


Anmelden zum Antworten