Immer Funktoren benutzen ?



  • abgesehen davon wird hier ein stateful functor benutzt, was zu bösen Überraschungen führen kann. Der Standard garantiert nämlich nicht, dass

    1. der Functor nicht kopiert wird und
    2. die Reihenfolge bei for_each immer von vorne nach hinten in einem Rutsch durchgeht.
      Eine Möglichkeit wäre z.B. dass bei jedem Schleifendurchlauf der Anfangs übergebene Functor kopiert wird und du am Ende mit einem vector voller Nullen dastehst, was ja nicht deine Absicht war.


    1. die Reihenfolge bei for_each immer von vorne nach hinten in einem Rutsch durchgeht.

    Der Standard garantiert, dass die Iteratoren in for_each() von first beginnend bis last - 1 durchgegangen werden. Das ist (soweit ich weiß) der einzige Algorithmus neben copy() , für den diese Garantie gegeben wird. Natürlich löst das das Problem mit der Kopie nicht.



  • Jopp, pumuckl - 1. stimmt zawr, aber 2. nicht:

    25.1.1 For each schrieb:

    Effects: Applies f to the result of dereferencing every iterator in the range [first, last), starting from first and proceeding to last - 1.

    das mit dem funktor hab ich aber noch nicht gewusst... hab den fehler vrmtl auch schon x-mal gemacht ><

    bb



  • Interessante Aspekte. Wie würde den ein Nicht-Stateful Funktor aussehen mit dem man 1. verhindern kann?



  • gehen würde es zum bsp. mit bind...
    und op() nimmt halt dann nen parameter mehr entgegen...

    bb



  • Was ist mit std::generate() ? In Verbindung mit std::back_inserter() kann man so auch im STL-Style Zahlen an leere Container anhängen.

    Der C++-Standard ist hier nicht 100% genau:

    25.2.6 schrieb:

    template<class ForwardIterator, class Generator>
    void generate(ForwardIterator first, ForwardIterator last, Generator gen);
    
    template<class OutputIterator, class Size, class Generator>
    void generate_n(OutputIterator first, Size n, Generator gen);
    

    1 Effects: Invokes the function object gen and assigns the return value of gen though all the iterators in the range [first, last) or [first, first + n).

    Dass die Iteratoren nicht in der Reihenfolge laufen, bedarf schon fast einer böswilligen Interpretation.



  • irgendwie muss ich jetzt an c++ denken



  • McCoolCool schrieb:

    Gibt es irgendeinen Grund warum ich mir einen Funktor schreiben sollte und damit den Vektor initialisere ...

    zunächst mal keinen (außer s.u.)

    Nexus schrieb:

    Da ist auch viel Geschmackssache dabei.

    Das ist wohl in letzter Instanz das ausschlaggebende Kriterium.

    volkard schrieb:

    Was wäre denn bei einem gigantisch großen vector schneller?

    Geschwindigkeit ist nicht alles, ein Kriterium 'pro Funktor' ist die schlichte Tatsache, dass man dabei weniger Fehler machen kann - wenn es der Compiler erst mal gefressen hat! Folgendes z.B.:

    for(int i=0;i<=zahlen.size();i++)
       zahlen[i] = i;
    

    wird zur Laufzeit nicht gleich schiefgehen, sondern vielleicht erst später und beim Kunden - und dann wird's teuer. Beim Einsatz von [begin(),end()) tut man sich schon schwerer, so einen Fehler zu machen.

    Aber wenn wir schon bei einem Container mit 10 Elementen über Geschwindigkeit reden, dann ist z.B. diese Lösung mit dem boost.counting_iterator

    #include <boost/iterator/counting_iterator.hpp>
    std::vector<unsigned int> zahlen( boost::counting_iterator< unsigned int >(0), boost::counting_iterator< unsigned int >( 10 ) );
    

    zumindest theoretisch fast um den Faktor 2 schneller, da die Initialisierung von vector<> mit dem Füllen desselben zusammenfällt. Ob sie's dann wirklich ist, hängt wohl im wesentlichen von den Fähigkeiten des verwendeten Compilers ab.
    Was oft vergessen wird ist, dass

    std::vector<unsigned int>zahlen(10);
    

    bereits eine interne Schleife mit vector<>.size() Durchläufen initiiert, um alle Elemente mit 0 zu belegen.

    Gruß
    Werner



  • pumuckl schrieb:

    abgesehen davon wird hier ein stateful functor benutzt, was zu bösen Überraschungen führen kann. Der Standard garantiert nämlich nicht, dass

    1. der Functor nicht kopiert wird und

    Wieso wäre das denn überhaupt ein Problem?
    Ich hab noch mal drüber nachgeguckt und wenn eine Kopie angelegt wird, dann sollte das doch auch keine Probleme machen!?

    bb



  • unskilled schrieb:

    Ich hab noch mal drüber nachgeguckt und wenn eine Kopie angelegt wird, dann sollte das doch auch keine Probleme machen!?

    Nicht in der heutigen Implementierung der stdlib.
    Bei dem Iteratorpaar ist alles übers Kopieren gesagt und das klappt auch.
    Bei dem Funktor, der sich wie ein Wert anfühlt, erwarte ich, daß normale Wert-Optimierungen greifen dürfen, wie daß mehrere Threads zum Array-Initialisieren benutzt werden, da macht das Kopieren Ärger.



  • EDIT:

    wurde schon gesagt, habe nicht genau genug gelesen 😞



  • Werner Salomon schrieb:

    Geschwindigkeit ist nicht alles, ein Kriterium 'pro Funktor' ist die schlichte Tatsache, dass man dabei weniger Fehler machen kann - wenn es der Compiler erst mal gefressen hat! Folgendes z.B.:

    for(int i=0;i<=zahlen.size();i++)
       zahlen[i] = i;
    

    wird zur Laufzeit nicht gleich schiefgehen, sondern vielleicht erst später und beim Kunden - und dann wird's teuer. Beim Einsatz von [begin(),end()) tut man sich schon schwerer, so einen Fehler zu machen.

    Was hat das jetzt mit Funktor zu tun? begin(),end() kann man in der Schleife auch ohne Funktor verwenden.


Anmelden zum Antworten