C++. Сборник рецептов - [97]
Итератор объявляется с помощью типа, элементы которого с его помощью будут перебираться. Например, в примере 7.1 используется >list
, так что итератор объявляется вот так.
>list
Если вы не работали со стандартными контейнерами, то часть этого объявления >::iterator
может выглядеть несколько необычно. Это вложенный в шаблон класса >list typedef
, предназначенный именно для этой цели — чтобы пользователи контейнера могли создать итератор для данного конкретного экземпляра шаблона. Это стандартное соглашение, которому следуют все стандартные контейнеры. Например, можно объявить итератор для >list
или для >set
, как здесь.
>list
>set
Возвращаясь обратно к нашему примеру, итератор о инициализируется первым элементом последовательности, который возвращается методом >begin
. Чтобы перейти к следующему элементу, используется >operator++
. Можно использовать как префиксный инкремент так и постфиксный инкремент (>p++
), аналогично указателям на элементы массивов, но префиксный инкремент не создает временного значения, так что он более эффективен и является предпочтительным. Постфиксный инкремент (>p++
) должен создавать временную переменную, так как он возвращает значение >p
до его инкрементирования. Однако он не может инкрементировать значение после того, как вернет его, так что он вынужден делать копию текущего значения, инкрементировать текущее значение, а затем возвращать временное значение. Создание таких временных переменных с течением времени требует все больших и больших затрат, так что если вам не требуется именно постфиксное поведение, используйте префиксный инкремент.
Как только будет достигнут элемент >end
, переход на следующий элемент следует прекратить. Или, строго говоря, когда будет достигнут элемент, следующий за >end
. В отношении стандартных контейнеров принято некое мистическое значение, которое представляет элемент, идущий сразу за последним элементом последовательности, и именно оно возвращается методом >end
. Этот подход работает в цикле >for
, как в этом примере:
>for (list
> p != lstStr.end(); ++p) {
> cout << *p << endl;
>}
Как только >p
станет равен >end
, >p
больше не может увеличиваться. Если контейнер пуст, то >begin == end
равно >true
, и тело цикла никогда не выполнится. (Однако для проверки пустоты контейнера следует использовать метод >empty
, а не сравнивать >begin
и >end
или использовать выражение вида >size == 0
.)
Это простое объяснение функциональности итераторов, но это не все. Во-первых, как только что было сказано, итератор работает как >rvalue
или >lvalue
, что означает, что его разыменованное значение можно присваивать другим переменным, а можно присвоить новое значение ему. Для того чтобы заменить все элементы в списке строк, можно написать нечто подобное следующему
>for (list
> p != lstStr.end(); ++p) {
> *p = "mustard";
>}
Так как >*p
ссылается на объект типа >string
, для присвоения элементу контейнера новой строки используется выражение >string::operator=(const char*)
. Но что, если >lstStr
— это объект типа >const
? В этом случае >iterator
не работает, так как его разыменовывание дает не-const объект. Здесь требуется использовать >const_iterator
, который возвращает только >rvalue
. Представьте, что вы решили написать простую функцию для печати содержимого контейнера. Естественно, что передавать контейнер следует как >const
-ссылку.
>template
>void printElements(const T& cont) {
> for(T::const_iterator p = cont.begin();
> p ! = cont.end(); ++p) {
> cout << *p << endl;
> }
>}
В этой ситуации следует использовать именно >const
, a >const_iterator
позволит компилятору не дать вам изменить >*p
.
Время от времени вам также может потребоваться перебирать элементы контейнера в обратном порядке. Это можно сделать с помощью обычного >iterator
, но также имеется >reverse_iterator
, который предназначен специально для этой задачи. >reverse_iterator
ведет себя точно так же, как и обычный >iterator
, за исключением того, что его инкремент и декремент работают противоположно обычному >iterator
и вместо использования методов >begin
и >end
контейнера с ним используются методы >rbegin
и >rend
, которые возвращают >reverse_iterator
. >reverse_iterator
позволяет просматривать последовательность в обратном порядке. Например, вместо инициализации >reverse_iterator
с помощью >begin
он инициализируется с помощью >rbegin
, который возвращает >reverse_iterator
, указывающий на последний элемент последовательности. >operator++
перемещает его назад — по направлению к началу последовательности, >rend
возвращает >reverse_iterator
, который указывает на элемент, находящийся перед первым элементом. Вот как это выглядит.
>for (list
> p != lstStr.rend(); ++p) {
> cout << *p << endl;
>}
Но может возникнуть ситуация, когда использовать >reverse_iterator
невозможно. В этом случае используйте обычный >iterator
, как здесь.
>for (list
> p != --lstStr.begin(); --p) {
Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
Система сборки программ, используемая во FreeBSD, имеет значительно большие возможности, чем те, которые мы задействовали. Какие это возможности и как их использовать в своих портах?
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.
«Как пасти котов» – это книга о лидерстве и руководстве, о том, как первое совмещать со вторым. Это, если хотите, словарь трудных случаев управления IT-проектами. Программист подобен кошке, которая гуляет сама по себе. Так уж исторически сложилось. Именно поэтому так непросто быть руководителем команды разработчиков. Даже если вы еще месяц назад были блестящим и дисциплинированным программистом и вдруг оказались в роли менеджера, вряд ли вы знаете, с чего надо начать, какой выбрать стиль руководства, как нанимать и увольнять сотрудников, проводить совещания, добиваться своевременного выполнения задач.