Advanced   Java   Services for-each Schleife (C++11)


for-each Schleife

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.


for-each mit primitiven Datentypen

Das folgende Beispiel ist am Anfang überraschend, jedoch kann man daraus sofort die richtigen Schlußfolgerungen ziehen.


Ausgeben eines int-Arrays mit for-each (Wertausgabe)

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

missing C++11-for-each-1.jpg

Offensichtlich ist dies eine reine Leseschleife, was bedeutet, daß elem eine Kopie des originalen Arrayelementes ist.


for-each Schleife mit einer Referenz

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

missing C++11-for-each-2.jpg

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).


Stanfard for-each arbeitet mit Kopien

Mit einer einfachen Klasse (oder struct) kann man leicht zeigen, daß bei einer Wertausgabe der Kopierkonstruktor verwendet wird.


Kopierkonstruktor wird aufgerufen

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:


for-each mit string-Referenzen

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

missing C++11-for-each-4.jpg


for-each mit const-Referenzen

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)