2010-10-13 4 views
18

in C++ 11 wir jetzt tun können:Ermöglicht C++ 11 for loop neue oder bessere Optimierungen?

void dosomething(std::vector<Thing>& things) 
{ 
    for(Thing& thing : things) 
    { 
     dofoo(thing); 
     wiizzz(thing); 
     tadaa(thing); 
    } 

} 

Ich weiß, dass die Zugabe und die Verwendung von Lambda-syntaktischer Zucker, aber es interessante Optimierungsmöglichkeiten bieten.

Was ist mit der for-Schleife? Ist es nur syntaktischer Zucker oder kann der Compiler einige Fälle optimieren, die mit der handgeschriebenen Schleife nicht oder nur schwer zu tun sind?

+0

Ist 'for (Ding & Ding: Dinge)' in C++ 0x eine Bestellung angeben? Oder könnte "Ding" in irgendeiner Reihenfolge erscheinen? – Inverse

+2

Es braucht nur den Iterator aus dem Begin() -Member des gegebenen Containers (wenn es eine Klasse ist) und iterieren, bis es den Ende() Iterator erreicht. Es ist also Iterator-abhängig oder containerabhängig, wenn Sie möchten. Im Falle eines rohen Arrays (oder Array semantische Klasse auch?) Es wird nur von einem [0] gehen und endet, wenn es zu einem [Größe]. – Klaim

Antwort

21

Es ist nur ein syntaktischer Zucker, da der Standard sagt, dass es mit Iteratoren zu einer Schleife äquivalent ist [bearbeiten: Das bedeutet, es keine weiteren Informationen an die für bearbeiten Schleife — Ende mit dem Äquivalent verglichen Compiler bereitstellt ]. Sie können eine bessere Leistung erhalten, obwohl, da es äquivalent ist zu:

for(auto iter = con.begin(), end = con.end(); iter != end; ++iter) 
{ 
    auto& ref = *iter; 
    // ... 
} 

während die meisten Menschen schreiben können:

for(auto iter = con.begin(); iter != con.end(); iter++) 
{ 
    // use *iter directly 
    // ... 
} 

die langsamer sein, wenn die con.end(), iter ++ oder * iter sind nicht trivial.

[bearbeiten:

Lambda ist syntaktischer Zucker

Nicht wirklich. Im Gegensatz zur for-Schleife ermöglicht es dem Compiler, den Stack-Frame-Basiszeiger direkt zu erfassen. Bei Variablen, die per Referenz erfasst werden, wird im Vergleich zu einem handgefertigten Funktionsobjekt eine Adressenindirektion pro Nutzung eingespart. — Ende bearbeiten]

+0

Sind Sie sicher, dass es 'end()' zwischenspeichert? Dies bedeutet, dass Sie die Auflistung, die semantisch unterschiedlich ist, nicht mutieren können (für Auflistungen, die Iteratoren beim Einfügen/Löschen nicht ungültig machen, z. B. "Liste"). – Motti

+0

Ich nehme an, dass davon ausgegangen wird, dass sich der Container nicht ändert. Wenn es geht, könnte die Verwendung von STL-Algorithmen ein besserer Weg sein. – Klaim

+3

@Motti: der Standard sagt ausdrücklich, dass es dem obigen Code entspricht (naja, ein bisschen komplizierter, weil es in Bezug auf die Bereiche formuliert ist). Wenn Ihr Container Iteratoren nicht ungültig macht, wird end() nicht ungültig gemacht. Also, was ist das Problem? Sie können den Container ändern, solange Sie diesen Code nicht verletzen. – ybungalobill

5

Vielleicht, aber wahrscheinlich nicht. Das mögliche Erstellen einer Index-/Counter-Variable, die nicht verwendet wird, wird dadurch eliminiert. Das ist nicht erforderlich für eine normale for-Schleife entweder, aber es ist viel wahrscheinlicher zu passieren, nur weil es das ist, was einige Leute tun zu tun.

Realistisch gesehen ist es unwahrscheinlich, dass dies auch nur einen Unterschied macht. Ich finde es zumindest schwer, sich ein Compiler-Team vorzustellen, das so ausgereift ist, dass es sogar den geringsten Wunsch hat, C++ 0x zu unterstützen, das den relativ trivialen Punkt des Erkennens und Eliminierens des Erstellens und Inkrementierens eines Schleifenindex nicht schon bewältigt hat nie benutzt.