Advanced Java Services | for-each Schleife (C++11) |
Wie in Sprachen wie Java oder C# schon lange eingeführt gibt es ab C++11 auch eine foreach-Schleife um
ohne Index auf die Elemente eines Arrays oder eines STL-Containers zuzugreifen.
C++ kommt dabei wie Java ohne neues Schlüsselwort aus.
Diese neue Schleife in C++ sollte nicht verwechselt werden klassischen 'for_each'-Funktion aus der
STL (Standard Template Library). Diese Funktion erhält als letztes Argument einen Funktionpointer.
Das folgende Beispiel ist am Anfang überraschend, jedoch kann man daraus sofort die richtigen Schlußfolgerungen ziehen.
Wir betrachten den folgenden einfachen Code
void for_each_using_values() { cout << endl << "Ausgabe eines Arrays mit for-each" << endl << endl; int intArr[] = { 0, 2, 4, 6, 8 }; for(int elem: intArr) cout << elem << ' ' ; cout << endl << endl; for(int elem: intArr) cout << ++elem << ' ' ; cout << endl << endl; for(int elem: intArr) cout << elem << ' ' ; }
Er macht die folgende Ausgabe
Offensichtlich ist dies eine reine Leseschleife, was bedeutet, daß elem eine Kopie des originalen Arrayelementes ist.
Verwenden wir Referenzen, sieht das ganze so aus.
void for_each_using_references()
{
cout << endl << "Ausgabe eines Arrays mit for-each" << endl << endl;
int intArr[] = { 0, 2, 4, 6, 8 };
for(int elem: intArr)
cout << elem << ' ' ;
cout << endl << endl;
for(int& elem: intArr)
cout << ++elem << ' ' ;
cout << endl << endl;
for(int elem: intArr)
cout << elem << ' ' ;
cout << endl << endl;
}
Die Ausgabe
Da eine Referenz auf den originalen Speicherplatz zugreift, hat man einen schreibenden Zugriff !
Will man das verhindern so nimmt man eine const-Referenz.
cout << endl << "Verwendung einer const-Referenz" << endl << endl; int intArr[] = { 0, 2, 4, 6, 8 }; for (const int& elem : intArr) cout << elem << ' '; cout << endl << endl;
Da eine Referenz auf den originalen Speicherplatz zugreift, hat man einen schreibenden Zugriff !
Das kann man mit einer const-referenz verhindern (siehe unten).
Mit einer einfachen Klasse (oder struct) kann man leicht zeigen, daß bei einer Wertausgabe der Kopierkonstruktor verwendet wird.
Hier unsere Testklasse.
class ForEachTest { public: ForEachTest() {}; ForEachTest(const ForEachTest& obj) { cout << "copy constructor" << endl; }; };
Hier ein simpler Programmausschnitt.
ForEachTest testArr[] = { ForEachTest(), ForEachTest(), ForEachTest() }; for(ForEachTest elem: testArr) ;
Er macht folgende Ausgabe:
Wir verwenden nun ein string-Array und zeigen, daß über Referenzen auf die Strings schreibend zugegriffen werden kann
string stringArr[] = { "ee", "i", "o", "um" };
for(string elem: stringArr)
cout << elem << ' ' ;
cout << endl;
for(string& elem : stringArr)
elem.insert(0, "f");
for(string elem: stringArr)
cout << elem << ' ';
cout << endl;
Die Funktion macht die folgende Ausgabe
Will man einen reinen Lesezugriff, so setzt man eine const-Referenz ein. Auf diese Weise verhindert man einen versehentlichen Schreibzugriff.
for(const string& elem : container)