Доступ к вектору с помощью итератора



 

Как вы знаете, массивы и указатели в C++ тесно связаны между собой. К элементам массива можно получить доступ как с помощью индекса, так и с помощью указателя. В библиотеке STL аналогичная связь существует между векторами и итераторами. Это значит, что к членам вектора можно обращаться как с помощью индекса, так и с помощью итератора. Эта возможность демонстрируется в следующей программе.

 

 

Вот как выглядят результаты выполнения этой программы.

 

 

В этой программе сначала создается вектор нулевой длины. Затем с помощью функции push_back() в конец вектора помещаются символы, в результате чего размер вектора соответствующим образом увеличивается.

Обратите внимание на то, как объявляется итератор р . Тип этого итератора определяется контейнерными классами. Поэтому для получения итератора для конкретного контейнера используйте объявление, аналогичное показанному в этом примере: просто укажите для данного итератора имя контейнера. В нашей программе итератор p инициализируется таким образом, чтобы он указывал на начало вектора (с помощью функции‑члена begin() ). Итератор, который возвращает эта функция, можно затем использовать для поэлементного доступа к вектору, инкрементируя его соответствующим образом. Этот процесс аналогичен тому, как можно использовать указатель для доступа к элементам массива. Чтобы определить, когда будет достигнут конец вектора, используется функция‑член end() . Эта функция возвращает итератор, установленный за последним элементом вектора. Поэтому, если значение р равно v.end() , значит, конец вектора достигнут.

 

Вставка и удаление элементов из вектора

 

Помимо занесения новых элементов в конец вектора, у нас есть возможность вставлять элементы в середину вектора, используя функцию insert() . Удалять элементы можно с помощью функции erase() . Использование функций insert() и erase() демонстрируется в следующей программе.

 

 

При выполнении эта программа генерирует следующие результаты.

 

Сохранение в векторе объектов класса

 

В предыдущих примерах векторы служили для хранения значений только встроенных типов, но этим их возможности не ограничиваются. В вектор можно помещать объекты любого типа, включая объекты классов, создаваемых программистом. Рассмотрим пример, в котором вектор используется для хранения объектов класса three_d . Обратите внимание на то, что в этом классе определяются конструктор по умолчанию и перегруженные версии операторов "<" и "==" . Имейте в виду, что, возможно, вам придется определить и другие операторы сравнения. Это зависит от того, как используемый вами компилятор реализует библиотеку STL.

 

 

Эта программа генерирует такие результаты.

 

 

Векторы обеспечивают безопасность хранения элементов, обнаруживая при этом чрезвычайную мощь и гибкость их обработки, но уступают массивам в эффективности использования. Поэтому для большинства задач программирования чаще отдается предпочтение обычным массивам. Однако возможны ситуации, когда уникальные особенности векторов оказываются важнее затрат системных ресурсов, связанных с их использованием.

 

О пользе итераторов

 

Частично сила библиотеки STL обусловлена тем, что многие ее функции используют итераторы. Этот факт позволяет выполнять операции с двумя контейнерами одновременно. Рассмотрим, например, такой формат векторной функции insert() .

 

 

Эта функция вставляет исходную последовательность, определенную параметрами start и end , в приемную последовательность, начиная с позиции i . При этом нет никаких требований, чтобы итератор i относился к тому же вектору, с которым связаны итераторы start и end . Таким образом, используя эту версию функции insert() , можно один вектор вставить в другой. Рассмотрим пример.

 

 

При выполнении эта программа генерирует следующие результаты.

 

 

Как видите, содержимое вектора v2 вставлено в середину вектора v .

По мере дальнейшего изучения возможностей, предоставляемых STL, вы узнаете, что итераторы являются связующими средствами, которые делают библиотеку единым целым. Они позволяют работать с двумя (и больше) объектами STL одновременно, но особенно полезны при использовании алгоритмов, описанных ниже в этой главе.

 

Списки

 

Списокэто контейнер с двунаправленным последовательным доступом к его элементам.

 

Класс list поддерживает функционирование двунаправленного линейного списка. В отличие от вектора, в котором реализована поддержка произвольного доступа, список позволяет получать к своим элементам только последовательный доступ. Двунаправленность списка означает, что доступ к его элементам возможен в двух направлениях: от начала к концу и от конца к началу.

Шаблонная спецификация класса list выглядит следующим образом.

 

 

Здесь T – тип данных, сохраняемых в списке, а элемент Allocator означает распределитель памяти, который по умолчанию использует стандартный распределитель. В классе list определены следующие конструкторы.

 

 

Конструктор, представленный в первой форме, создает пустой список. Вторая форма предназначена для создания списка, который содержит num элементов со значением val . Третья создает список, который содержит те же элементы, что и объект ob . Четвертая создает список, который содержит элементы в диапазоне, заданном параметрами start и end .

Для класса list определены следующие операторы сравнения:

 

 

Функции‑члены, определенные в классе list , перечислены в табл. 21.3. В конец списка, как и в конец вектора, элементы можно помещать с помощью функции push_back() , но с помощью функции push_front() можно помещать элементы в начало списка. Элемент можно также вставить и в середину списка, для этого используется функция insert() . Один список можно поместить в другой, используя функцию splice() . А с помощью функции merge() два списка можно объединить и упорядочить результат.

 

 

 

 

 

 

 

 

 

 

 

 

Чтобы достичь максимальной гибкости и переносимости для любого объекта, который подлежит хранению в списке, следует определить конструктор по умолчанию и оператор "<" (и желательно другие операторы сравнения). Более точные требования к объекту (как к потенциальному элементу списка) необходимо согласовывать в соответствии с документацией на используемый вами компилятор.

Рассмотрим простой пример списка.

 

 

Результаты выполнения этой программы таковы:

 

 

При выполнении эта программа создает список символов. Сначала создается пустой объект списка. Затем в него помещается десять букв (от А до J ). Заполнение списка реализуется путем использования функции push_back() , которая помещает каждое новое значение в конец существующего списка. После этого отображается размер списка и его содержимое. Содержимое списка выводится на экран в результате выполнения следующего кода.

 

 

Здесь итератор p инициализируется таким образом, чтобы он указывал на начало списка. При выполнении очередного прохода цикла итератор р инкрементируется, чтобы указывать на следующий элемент списка. Этот цикл завершается, когда итератор р указывает на конец списка. Применение подобных циклов – обычная практика при использовании библиотеки STL. Например, аналогичный цикл мы применили для отображения содержимого вектора в предыдущем разделе.

Поскольку списки являются двунаправленными, заполнение их элементами можно производить с обоих концов. Например, при выполнении следующей программы создается два списка, причем элементы одного из них расположены в порядке, обратном по отношению к другому.

 

 

Эта программа генерирует такие результаты.

 

 

В этой программе список реверсируется путем удаления элементов с начала списка lst и занесения их в начало списка revlst .

 

Сортировка списка

 

Список можно отсортировать с помощью функции‑члена sort() . При выполнении следующей программы создается список случайно выбранных целых чисел, который затем упорядочивается по возрастанию.

 

 

Вот как может выглядеть один из возможных вариантов выполнения этой программы.

 


Дата добавления: 2018-09-22; просмотров: 514; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!