====================== Einsatz von Iteratoren [TOC] ====================== Wenn eine neue Datenstruktur mit Inhalten aus einer anderen Datenstruktur zu füllen ist, dann ist es gut, wenn wir ebenfalls auf den Einsatz des _default constructor_ verzichten können. Stattdessen sollte sogleich der Kopierkonstruktor zum Zuge kommen. Naheliegend ist es hier, einen Konstruktor anzubieten, der ein Paar von Iteratoren akzeptiert. So könnte eine Verwendung aussehen: ---- CODE (type=cpp) ---------------------------------------------------------- #include "array.hpp" int main() { int values[] = {2, 3, 5, 7, 11, 13}; std::size_t dim = sizeof(values)/sizeof(values[0]); Array a(values, values + dim); } ------------------------------------------------------------------------------- Da wir beim _Array_ die Dimensionierung sogleich festlegen müssen, geht dies nur, wenn die Iteratoren den Bedingungen eines _random access iterator_ genügen, d.h. mit der Differenz zweier Zeiger könnten wir sogleich die Zahl der Elemente bestimmen. Alternativ könnte auch die generische Funktion `std::distance(it1, it2)` aus `#include ` verwendet werden, die bei _random access iterators_ konstanten Aufwand hat, im allgemeineren Fall von Forward-Iteratoren einen linearen Aufwand benötigt. Ebenfalls wäre es reizvoll, wenn die Elemente eines Arrays mit Iteratoren durchlaufen werden könnten. Hierzu werden die Methoden _begin_ und _end_ benötigt. In Fällen wie diesen wäre es sogar besonders einfach, da reguläre Zeiger verwendet werden können und somit der Aufwand entfällt, eine spezielle Iterator-Klasse zu entwickeln. Wie bei den Zugriffsoperatoren ist dann aber sowohl der Fall mit und ohne Schreibschutz zu berücksichtigen. Aufgaben und Fragen =================== * Fügen Sie einen wie oben beschriebenen Konstruktor hinzu, der als Parameter ein Iteratoren-Paar erhält und der alle Elemente des Arrays kopierkonstruiert aus der von den Iteratoren spezifizierten Datenbestand. Folgendes Testprogramm sollte dann funktionieren: :import: session04/step04/test1.cpp Was erwarten Sie als Ausgabe bei folgendem Testprogramm, wenn es wie folgt aufgerufen wird: :import: session04/step04/test2.cpp ---- CODE (type=sh) -------------------------------------- g++ -Wall -o test2 test2.cpp echo 1 2 3 | ./test2 ---------------------------------------------------------- Denken Sie kurz darüber nach, bevor Sie es ausprobieren. Und wenn Sie nicht darauf gekommen sind, denken Sie nach, woran es liegt und wie Sie mit diesem Fall umgehen könnten. Um initialisierte von uninitialisierten Werten sauber unterscheiden zu können, hilft vielleicht auch noch folgendes Testprogramm, das den Wert 42 für per _default constructor_ konstruierte Elemente nimmt: :import: session04/step04/test3.cpp [fold] Wie auch immer Sie das Problem lösen, sollten Sie darauf achten, dass es auch ohne _default constructor_ klappt: :import: session04/step04/test4.cpp [fold] * Fügen Sie wie oben beschrieben die Methoden _begin_ und _end_ hinzu, wobei Sie wie beim Zugriffsoperator beide Varianten unterstützen sollten. Ein erstes Testprogramm hierzu, das eine auf Iteratoren basierende _for range loop_ verwendet: :import: session04/step04/test5.cpp Funktioniert bei Ihnen dann auch folgender Test? :import: session04/step04/test6.cpp Interessant wird es, wenn Sie auf die Elemente mit so einer Schleife schreibenderweise zugreifen möchten. Kann folgender Versuch zum Initialisieren eines Arrays funktionieren? Wenn nein, woran liegt es und wie kann das korrigiert werden? :import: session04/step04/test7.cpp :navigate: up -> doc:index back -> doc:session04/page06 next -> doc:session04/page08