Vorteile von unterschiedlichen for-Schleifen: for(int a : vec), BOOST_FOREACH(a,vec), for(auto a=vec.begin();a!=vec.end(



  • Hallo,

    gibt es irgendeinen Vorteil von:

    for(int a : vec)
    {
    
    }
    

    gegenueber:

    for(auto a=vec.cbegin();a!=vec.cend();a++)
    {
    }
    

    Die erste Schleife ist weniger Schreibarbeit fuer mich, aber gibt es einen unterschied fuer den Compiler?

    ­čÖé



  • Ja, die erste Schleife kann optimierr sein.
    Nd sie ist auf jeden Fall besser als deine, die in jedem Durchlauf cend() aufruft.



  • In der Praxis gibt es wohl nur selten einen Unterschied, da der end()-Aufruf geinlined werden kann.
    Dennoch ist range based for einfacher zu schreiben, einfacher zu lesen und somit auch einfacher zu warten.
    BOOST_FOREACH ist fuer Compiler, die kein range based for koennen.
    std::for_each ist manchmal auch eine gute Loesung.
    Rohe for-schleifen Schleifen braucht man verhaeltnismaesig selten und sollte die anderen bevorzugen.



  • Marthog schrieb:

    In der Praxis gibt es wohl nur selten einen Unterschied, da der end()-Aufruf geinlined werden kann.

    Also im Going Native 2013 Beitrag wo ├╝ber Range-Based-For gesprochen wurde, wurde behauptet dass es in der Praxis eben doch einen Unterschied macht. Weil die end() Aufrufe eben oft nicht aus der Schleife rausgezogen werden k├Ânnen.

    (Inlining geht wohl meistens, ja. Ohne dass der Compiler erkennt dass das Ergebnis von end() Konstant ist, und die Berechnung aus der Schleife rauszieht, wird die "manuelle" Schleife aber trotzdem langsamer sein.)



  • F├╝r die Diskussion zur Performance von Range Based For siehe hier.



  • hustbaer schrieb:

    Marthog schrieb:

    In der Praxis gibt es wohl nur selten einen Unterschied, da der end()-Aufruf geinlined werden kann.

    Also im Going Native 2013 Beitrag wo ├╝ber Range-Based-For gesprochen wurde, wurde behauptet dass es in der Praxis eben doch einen Unterschied macht. Weil die end() Aufrufe eben oft nicht aus der Schleife rausgezogen werden k├Ânnen.

    (Inlining geht wohl meistens, ja. Ohne dass der Compiler erkennt dass das Ergebnis von end() Konstant ist, und die Berechnung aus der Schleife rauszieht, wird die "manuelle" Schleife aber trotzdem langsamer sein.)

    Wenn das so ist, dann geh da nicht mehr hin, w├╝rde ich sagen.



  • Wei├č nicht, das wurde von den Typen behauptet die die Compiler schreiben, man sollte meinen die wissen sowas.



  • @volkard
    Wo hin?
    Ich hab mir den Beitrag online angesehen.

    Davon abgesehen weiss ich selbst dass es F├Ąlle gibt wo der Compiler nicht erkennen kann dass bei end() immer das selbe rauskommt. Wenn ich deinen Beitrag richtig deute, also wenn du behaupten willst dass die "kann nicht optimiert werden" Behauptung Bl├Âdsinn ist, dann muss ich da ganz klar widersprechen.

    Beispiel:

    void Foo::Bar()
    {
        std::vector<Baz> batzen;
        for (auto it = m_baz.begin(); it != m_baz.end(); ++it)
            if (very_selective_condition(*it))
                batzen.push_back(*it);
    }
    

    Ein Compiler kann hier nur sinnvoll optimieren, wenn er beweisen kann dass m_baz nicht ├╝ber den " new Handler" ( _set_new_handler() ) modifiziert werden kann. Und das wird i.A. ziemlich schwer zu beweisen sein.
    Dazu m├╝sste er entweder beweisen dass die Adresse des Foo-Objekts mit dem gearbeitet wird nur lokal bekannt ist, oder dass im ganzen Programm kein new Handler gesetzt wird. Oder dass alle new Handler "brav" sind.

    Die erste Option (Adresse des Objekts nur lokal Bekannt) halte ich dabei noch f├╝r halbwegs realistisch. Die f├Ąllt aber auch flach sobald Foo::Bar nicht selbst inline erweitert wird, und das wird durchaus kein seltener Fall sein. Wenn man DLLs verwendet hat man den sogar andauernd.
    Die anderen Varianten halte ich f├╝r v├Âllig utopisch.

    (OK, theoretisch w├Ąre noch m├Âglich dass der Compiler Code erzeugt der m_baz.end() nur neu berechnet wenn mal push_back aufgerufen wurden. Das halte ich aber auch f├╝r reichlich weit hergeholt.)



  • Ich meinte eher im Sinne von "Zeitverschwendung, zugeh├Ârt zu haben", vor allem wegen

    a) Wer bei

    for(auto a=vec.cbegin();a!=vec.cend();a++)
    

    unsicher ist, schreibt schon lange

    for(auto a=vec.cbegin(),e=vec.cend();a!=e;++a)
    

    und auch ein wenig wegen

    b) Man kann meistens wohl erwarten, da├č end() inline ist und h├Âchstens einen Attribut-Zugriff macht, und das im Cache liegt, ich sehe keinen Bedarf, hier Performanceerw├Ągungen ins Feld zu f├╝hren. So, wie ich oft kein lokales e aushebe.



  • ForWas schrieb:

    gibt es irgendeinen Vorteil von:

    for(int a : vec)
    {
    
    }
    

    gegenueber:

    for(auto a=vec.cbegin();a!=vec.cend();a++)
    {
    }
    

    ?

    Nimm einfach das, von dem du glaubst, dass das f├╝r andere sehr gut lesbar wird. Bei dem l├Ąngeren for kann ein Leser nicht auf einen Blick erkennen, was da passiert. Er muss alle drei Teile ├╝berpr├╝fen. Und dann kommt raus, dass es doch nur ein Loop ├╝ber alle Elemente ist (sofern da kein break drin steht). Deswegen fand ich std::for_each auch nicht so schlecht von der Idee her. Da steht ja schon im Namen drin, wie und wor├╝ber iteriert werden soll. Nur ist das mit dem Iterator-Paar, was anzugeben ist, etwas l├Ąstig und ohne polymorphe Lambdas muss man da auch schon wieder zu viel schreiben.

    Manches an Schreibarbeit kann man sich aber mit'nem f├Ąhigen Editor sparen. Zum Beispiel bietet ein sehr einfacher Editor (gedit f├╝r *nix) ein "Snippets"-Feature an, mit dem man sich Tipparbeit sparen kann. Das Ding ist mit Python script-bar. So generiere ich auch inzwischen Include-Guards (einfach ein paar Bytes von /dev/random nehmen und die auf INCLUDE_GUARD_XXXXXXXXXXXXXXXXXXXXXXXXXX mappen, wobei X jeweils ein zuf├Ąlliges Zeichen aus [A-Z,0-9] ist. In der Hinsicht unterscheiden sich deine zwei Varianten nicht besonders. Mit entsprechender Editor-Konfiguration l├Ąsst sich beides ├Ąhnlich schnell tippen.



  • volkard schrieb:

    Ich meinte eher im Sinne von "Zeitverschwendung, zugeh├Ârt zu haben"

    War es ganz sicher nicht.


Log in to reply