foreach und C++

Dezember 15th, 2007 | Kategorien: C#, C++ | Tags:

Irgendwie wurde ich nun schon zweimal innerhalb von wenigen Tagen auf die Problematik angesprochen, wie man in C++ Arrays andere Container durchlaufen kann. Die meisten Leute verweisen dann auf Sprachen wie C# oder PHP, wo das mittels der foreach Schleife ja auch wirklich sehr einfach geht.

string[] strings = {"Foo", "Bar", "Foobar"};
foreach (string s in strings)
{
    Console.WriteLine(s);
}

Der obige Quellcode in C# würde nun einfach das Array strings in der Konsole ausgeben. Wenn es nun an C++ geht, findet man bei vielen Leuten ungefähr den folgenden Code:

std::string strings[3] = {"Foo", "Bar", "Foobar"};
for (int i = 0; i < 3; i++)
{
    std::cout << strings[i] << std::endl;
}

Und jo, wenn man das auf die gezeigte Art und Weise macht, dann muss man leider weiterhin per Indexoperator auf die einzelnen Strings zugreifen. Aber mal im Ernst, Arrays sind doch sehr C ;)

C++ kommt im Verbund mit der STL und die STL bietet einen Ausweg aus diesem Dilemma: Iteratoren. Per Iterator lässt sich eine foreach Schleife in C++ ungefähr so darstellen:

typedef std::vector<std::string> stringvector;
 
stringvector strings;
strings.push_back("Foo");
strings.push_back("Bar");
strings.push_back("Foobar");
 
for (stringvector::iterator it = strings.begin(); it != strings.end(); it++)
{
    std::cout << *it << std::endl;
}

Da es sich bei std::vector nicht um ein Sprachelement von C++ handelt, müssen wir ihn in diesem Fall mit der push_back Methode füllen, aber das ist sowieso realitätsnaher ;)

Spannender ist die for Schleife. Anstatt wie gewohnt einen integer zum Zählen zu benutzen, machen wir uns das Verhalten von Iteratoren zunutze. Diese lassen sich wie integer vergleichen und inkrementieren bzw. dekrementieren. Wir initialisieren unseren Iterator mit dem ersten Element unseres Vektors, prüfen in der Bedinung ob wir schon am Ende angelangt sind und inkrementieren den Iterator nach jedem Durchlauf.

Wichtig ist aber, dass man den Iterator, wenn man auf seinen Inhalt zugreifen möchte, mit dem * oder -> Operator dereferenzieren muss.

No comments yet.