Как получить итератор на элемент vector
Итераторы обеспечивают доступ к элементам контейнера. С помощью итераторов очень удобно перебирать элементы. Итератор описывается типом iterator . Но для каждого контейнера конкретный тип итератора будет отличаться. Так, итератор для контейнера list<int> представляет тип list<int>::iterator , а итератор контейнера vector<int> представляет тип vector<int>::iterator и так далее.
Для получения итераторов контейнеры в C++ обладают такими функциями, как begin() и end() . Функция begin() возвращает итератор, который указывает на первый элемент контейнера (при наличии в контейнере элементов). Функция end() возвращает итератор, который указывает на следующую позицию после последнего элемента, то есть по сути на конец контейнера. Если контейнер пуст, то итераторы, возвращаемые обоими методами begin и end совпадают. Если итератор begin не равен итератору end, то между ними есть как минимум один элемент.
Обе этих функции возвращают итератор для конкретного типа контейнера:
В данном случае создается вектор — контейнер типа vector, который содержит значения типа int. И этот контейнер инициализируется набором <1, 2, 3, 4>. И через метод begin() можно получить итератор для этого контейнера. Причем этот итератор будет указывать на первый элемент контейнера.
Операции с итераторами
С итераторами можно проводить следующие операции:
*iter : получение элемента, на который указывает итератор
++iter : перемещение итератора вперед для обращения к следующему элементу
—iter : перемещение итератора назад для обращения к предыдущему элементу. Итераторы контейнера forward_list не поддерживают операцию декремента.
iter1 == iter2 : два итератора равны, если они указывают на один и тот же элемент
iter1 != iter2 : два итератора не равны, если они указывают на разные элементы
Например, используем итераторы для перебора элементов вектора:
При работе с контейнерами следует учитывать, что добавление или удаление элементов в контейнере может привести к тому, что все текущие итераторы для данного контейнера, а также ссылки и указатели на его элементы станут недопустимыми.
Итераторы позволяют не только получать элементы, но и изменять их:
В данном случае в цикле while элементы вектора возводятся в квадрат. Консольный вывод данной программы:
Константные итераторы
Если контейнер представляет константу, то для обращения к элементам этого контейнера можно использовать только константный итератор (тип const_iterator ). Такой итератор позволяет считывать элементы, но не изменять их:
Для получения константного итератора также можно использовать функции cbegin() и cend . При этом даже если контейнер не представляет константу, но при этом для его перебора используется константный итератор, то опять же нельзя изменять значения элементов этого контейнера:
Реверсивные итераторы
Реверсивные итераторы позволяют перебирать элементы контейнера в обратном направлении. Для получения реверсивного итератора применяются функции rbegin() и rend() , а сам итератор представляет тип :
Консольный вывод программы:
Если надо обеспечить защиту от изменения значений контейнера, то можно использовать константный реверсивный итератор, который представлен типом const_reverse_iterator и который можно получить с помощью функций crbegin() и crend() :
Также итераторы для всех типов, кроме list и forward_list, поддерживают ряд дополнительных операций:
iter + n : возвращает итератор, который смещен от итератора iter на n позиций вперед
iter — n : возвращает итератор, который смещен от итератора iter на n позиций назад
iter += n : перемещает итератор на n позиций вперед
iter -= n : перемещает итератор на n позиций назад
iter1 — iter2 : возвращает количество позиций между итераторами iter1 и iter2
>, >=, <, <= : операции сравнения. Один итератор больше другого, если указывает на элемент, который ближе к концу
C++. Класс vector. Методы, обеспечивающие доступ к элементам массива
Класс vector . Методы, обеспечивающие доступ к элементам массива. Методы at() , front() , back() , data() , begin() , end() , cbegin() , cend() , rbegin() , rend() , crbegin() , crend()
Перед изучением данной темы рекомендуется ознакомиться со следующей темой:
Содержание
- 1. Метод at() . Получить элемент вектора по его позиции
- 2. Метод front() . Возвращает ссылку на первый элемент вектора
- 3. Метод back() . Возвращает ссылку на последний элемент вектора
- 4. Метод data() . Получить указатель на вектор
- 5. Метод begin() . Вернуть итератор, указывающий на первый элемент вектора
- 6. Метод end() . Вернуть итератор, указывающий на последний элемент массива
- 7. Методы cbegin() , cend() . Установить константный итератор на начало и конец массива
- 8. Методы rbegin() , rend() . Доступ к элементам массива с помощью реверсного итератора
- 9. Методы crbegin() , crend() . Установить на начало и конец массива константный реверсный итератор
Поиск на других ресурсах:
1. Метод at() . Получить элемент вектора по его позиции
Метод at() используется для доступа к конкретному элементу массива на основе заданного индекса. Метод имеет 2 перегруженные реализации
здесь T – тип элементов массива.
Первая реализация используется для чтения элемента из массива. Вторая реализация используется для изменения элемента массива.
Пример.
2. Метод front() . Возвращает ссылку на первый элемент вектора
С помощью метода front() можно получить ссылку на первый элемент массива. Синтаксис объявления двух перегруженных реализаций метода следующий
Первая реализация метода позволяет считывать значение первого элемента массива. Вторая реализация позволяет записывать значения в первый элемент массива.
Пример.
3. Метод back() . Возвращает ссылку на последний элемент вектора
Чтобы получить доступ к последнему элементу вектора используется метод back() . Этот метод имеет 2 перегруженных реализации, синтаксис объявления которых следующий
Первая реализация используется, когда нужно считать значение из последнего элемента вектора. Вторая реализация используется, когда нужно записать значение в последний элемента вектора.
Пример.
4. Метод data() . Получить указатель на вектор
Метод data() позволяет получить указатель на динамический массив. С помощью этого указателя можно иметь доступ к элементам вектора как к обычному массиву.
Синтаксис объявления метода следующий:
тут T – тип элементов вектора.
Пример.
5. Метод begin() . Вернуть итератор, указывающий на первый элемент вектора
Метод begin() возвращает итератор, указывающий на первый элемент динамического массива. Метод имеет следующую общую форму:
здесь T – тип элементов массива.
Пример.
6. Метод end() . Вернуть итератор, указывающий на последний элемент массива
Метод end() устанавливает итератор на конец массива. Это означает, что итератор установлен на элемент, следующий за последним элементом массива.
Рисунок 1. Установка итераторов методами begin() и end() . Размер массива size()
Синтаксис объявления метода следующий
Пример.
7. Методы cbegin(), cend() . Установить константный итератор на начало и конец массива
При работе с итераторами, кроме обычных итераторов различают константные итераторы. В библиотеке STL стандартный итератор объявляется с использованием типа iterator
Константный итератор объявляется с использованием типа constant_iterator
- T – тип элементов массива;
- constant_iterator – тип, определяющий константный итератор;
- ConstIt – имя константного итератора.
В отличие от обычного (стандартного) итератора, невозможно изменить значение элемента массива с константным итератором. То есть, присваивание константному итератору некоторого значения value
вызовет ошибку компиляции.
Методы cbegin() и cend() предназначены для получения константного итератора, который указывает соответственно на начало и конец массива. Общая форма объявления методов следующая
здесь T – тип элементов массива.
Метод cend() возвращает итератор, указывающий на элемент, следующий за последним элементом массива.
Пример.
8. Методы rbegin() , rend() . Доступ к элементам массива с помощью реверсного итератора
Реверсный итератор отличается от обычного итератора тем, что порядок следования элементов рассматривается от конца к началу. С этой точки зрения вносятся все возможные изменения в методах обработки и операциях над итераторами. Так, например, операция приращения итератора it++ осуществляет переход к предыдущему элементу итератора, а не к следующему, как в обычном итераторе.
Реверсный итератор объявляется с использованием ключевого слова reverse_iterator
- T – тип элементов вектора;
- itReverse – имя итератора.
Методы rbegin() rend () работают с реверсными итераторами. Они позволяют получить итераторы, указывающие соответственно на начало ( rbegin ) и конец ( rend ) массива. Методы имеют следующие перегруженные реализации
Одна из реализаций методов rbegin() и rend() позволяет работать как обычный итератор, допускающий чтение/запись. Вторая реализация этих методов работает как константный итератор, допускающий только чтение.
Пример.
- T – тип элементов массива;
- itConstReverse – имя константного реверсного итератора.
Изменить значение элементов массива с помощью константного реверсного итератора не удастся.
Методы crbegin() , crend() предназначены для работы с типом константного реверсного итератора constant_reverse_iterator и имеют следующие объявления
Урок №198. Итераторы STL
Итератор — это объект, который способен перебирать элементы контейнерного класса без необходимости пользователю знать реализацию определенного контейнерного класса. Во многих контейнерах (особенно в списке и в ассоциативных контейнерах) итераторы являются основным способом доступа к элементам этих контейнеров.
Функционал итераторов
Об итераторе можно думать, как об указателе на определенный элемент контейнерного класса с дополнительным набором перегруженных операторов для выполнения четко определенных функций:
Оператор * возвращает элемент, на который в данный момент указывает итератор.
Оператор ++ перемещает итератор к следующему элементу контейнера. Большинство итераторов также предоставляют оператор −− для перехода к предыдущему элементу.
Операторы == и != используются для определения того, указывают ли оба итератора на один и тот же элемент или нет. Для сравнения значений, на которые указывают оба итератора, нужно сначала разыменовать эти итераторы, а затем использовать оператор == или оператор != .
Оператор = присваивает итератору новую позицию (обычно начальный или конечный элемент контейнера). Чтобы присвоить значение элемента, на который указывает итератор, другому объекту, нужно сначала разыменовать итератор, а затем использовать оператор = .
Каждый контейнерный класс имеет 4 основных метода для работы с оператором = :
метод begin() возвращает итератор, представляющий начальный элемент контейнера;
метод end() возвращает итератор, представляющий элемент, который находится после последнего элемента в контейнере;
метод cbegin() возвращает константный (только для чтения) итератор, представляющий начальный элемент контейнера;
метод cend() возвращает константный (только для чтения) итератор, представляющий элемент, который находится после последнего элемента в контейнере.
Может показаться странным, что метод end() не указывает на последний элемент контейнера, но это сделано в целях упрощения использования циклов: цикл перебирает элементы до тех пор, пока итератор не достигнет метода end(), и тогда уже всё — «Баста!».
Наконец, все контейнеры предоставляют (как минимум) два типа итераторов:
container::iterator — итератор для чтения/записи;
container::const_iterator — итератор только для чтения.
Рассмотрим несколько примеров использования итераторов.
Итерация по вектору
Заполним вектор 5-ю числами и с помощью итераторов выведем значения вектора:
C++ STL Vectors: Get iterator from index?
So, I wrote a bunch of code that accesses elements in an stl vector by index[], but now I need to copy just a chunk of the vector. It looks like vector.insert(pos, first, last) is the function I want. except I only have first and last as ints. Is there any nice way I can get an iterator to these values?
5 Answers 5
way mentioned by @dirkgently ( v.begin() + index ) nice and fast for vectors
but std::advance ( v.begin(), index ) most generic way and for random access iterators works constant time too.
EDIT
differences in usage:
added after @litb notes.
Also; auto it = std::next(v.begin(), index);
Update: Needs a C++11x compliant compiler
You can always use std::advance to move the iterator a certain amount of positions in constant time:
Actutally std::vector are meant to be used as C tab when needed. (C++ standard requests that for vector implementation , as far as I know — replacement for array in Wikipedia) For instance it is perfectly legal to do this folowing, according to me:
Of course, either foo must not copy the address passed as a parameter and store it somewhere, or you should ensure in your program to never push any new item in vec, or requesting to change its capacity. Or risk segmentation fault.