vector oder itartoren (begin/end) an eine funktion übergeben



  • Ich erinnere mich an einen post hier, den ich leider nicht finden kann in dem es hiess, dass man besser die iteratoren übergebensollte:

    void methode( std::vector<a>::const_iterator begin , std::vector<a>::const_iterator end ) 
    {
      for(  ; begin != end ; begin++ )
      {
        // ...
      }
    }
    

    anstatt

    void methode( const vstd::ector<a> &myvector  ) 
    {
      for( vector<a>::const_iterator i = myvector.begin() ; i != myvector.end() ; i++ )
      {
        // ...
      }
    }
    

    den ganzen vector an die funktion zu schicken. Wie sieht ihr das? Oder ist es nicht so relevant?


  • Mod

    void methode( std::vector<a>::const_iterator begin , std::vector<a>::const_iterator end )
    

    So ist das natürlich herzlich witzlos, das ist bloß umständlich. Interessant wird es, wenn du das mit Templates mischt:

    template<typename Iterator> void methode( Iterator begin , Iterator end )
    

    Bei deiner Funktion werden nämlich gar keine vector-spezifischen Eigenschaften benutzt, warum sollte man sich dann auf vector festlegen? Denn nun ist es auf einmal egal, was für eine Art Container dahinter steht, Hauptsache er kann von einem Element mittels ++ zum nächsten. Das gilt beispielsweise für alle STL-Container und sogar für Arrays. So hast du ohne Kosten und mit minimalem Programmieraufwand deine Funktion universell einsetzbar gemacht.

    Eine gute Orientierung sind die algorithms aus der STL, die diese Konzepte konsequent durchziehen:
    http://www.cplusplus.com/reference/algorithm/
    Diese Art des Designs hat sehr viel Anklang gefunden und viele moderne C++-Bibliotheken sind so aufgebaut.

    (Neuerdings vertreten ja einige Gurus die Ansicht, dass "Ranges" ein noch besseres Konzept sind, aber das würde jetzt zu weit führen. Guck dir erst einmal an, wie die STL aufgebaut ist.)



  • In den meisten Fällen, in denen man also so ein Paar von Iteratoren oder den Container selbst übergeben will, gibt es schon eine STL-Funktion, die eben selbiges über den funktionalen Weg erledigen kann. for_each mit Lambdas etc.. Nur wenn man selber etwas Container-artiges erstellen will stellt sich meiner Meinung nach die Frage und dort sind die Schnittstellen am besten ähnlich zu dem, was man aus der STL so gewöhnt ist.

    PS: SeppJ hat jetzt nicht den typedef-Weg aufgezeigt für die Iterator-Typen. Man muss nicht wirklich immer gleich ein Template auspacken.


  • Mod

    Decimad schrieb:

    PS: SeppJ hat jetzt nicht den typedef-Weg aufgezeigt für die Iterator-Typen. Man muss nicht wirklich immer gleich ein Template auspacken.

    Ich sehe hier keinen Vorteil durch einen globalen typedef. Jedoch viele Vorteile eines Templates gegenüber dem typedef. Meinst du etwas anderes?



  • Nun, ich finde Templates toll und spiele gerne mit ihnen rum, freue mich dann dass alles so toll funktioniert (und über die schönen Fehlermeldungen), aber ich mag überhaupt nicht, dass der ganze Source in Header muss. Wenn ich mich also nur auf einen abhängigen, aber festen Typ stütze, nehme ich lieber typedefs, denn ein generelles Template für alle Typen zu schreiben, obwohl es überhaupt nur einen Typ gibt. Kommt nicht allzu oft vor, aber passiert halt und deshalb wollte ich diese Möglichkeit der Vollständigkeit halber erwähnt haben.



  • Da kannst du aber halt auch gleich den Container übergeben. (Nun ja, es sei denn es ist nicht immer klar, dass man etwas auf dem ganzen Container machen will. Dann lohnen Iteratoren wohl auch so. :xmas1: )



  • Genau!
    So, ich möchte jetzt hier bei der Gelegenheit auch einmal Weihnachten zelebrieren! :xmas1: :xmas2: :xmas1:




Anmelden zum Antworten