Как end() реализуется в контейнерах STL?

Итак, когда нам нужно пересекать контейнер от начала до конца, мы пишем что-то вроде

for (i = v->begin(); i != v->end(); i++)

Предполагая, что i является итератором для контейнера v.

Мой вопрос: "Какие гарантии, что конец всегда будет указывать на один последний элемент в контейнере?" Как STL обеспечивает такое поведение и есть ли вероятность, что этот случай не соответствует действительности?

Ответ 1

STL обеспечивает такое поведение, всегда сохраняя такие вещи:

vector

В конце (каламбур) не имеет значения, что end() , если он всегда end() (и, очевидно, его нельзя путать с любым другим node).

Ответ 2

Спецификация stl гарантирует, что конец будет один за концом См. здесь. Это всегда будет так. Точно как это может зависеть от реализации (иногда значения просто устанавливаются на нуль, например), но будьте уверены, что ваш цикл будет в порядке, пока v является допустимым указателем.

Ответ 3

С++ 03 Раздел 23.1/7 говорит

begin() возвращает итератор, ссылаясь на первый элемент в контейнере.

end() возвращает итератор, который является значением last-end-end для контейнера.

Если контейнер пуст, то begin() == end();

Ответ 4

"end всегда указывает на один последний элемент в контейнере" означает, что если вы увеличиваете итератор, указывающий на последний элемент, он будет равен результату end(). Реализация может быть разной. В Visual С++ std::vector::end() возвращается конкретный итератор реализации, содержащий нулевой указатель.

Ответ 5

Вы спрашиваете обо всех контейнерах STL... не упоминание о конкретном векторе, где end() может быть реализовано, как вы, очевидно, интуитивно ожидаете. Что за конец в std:: map < > ? "Конец один за последним использованным node" - это всего лишь логическое понятие, выражающее, что вы можете безопасно увеличивать его от последнего используемого node, дифференцировать/приравнивать его от/к абстрактному понятию "конец", и выполните некоторую арифметику node, где конец считается еще одним, чем последний использованный node. Не воспринимайте это слишком буквально.

Ответ 6

Как уже отмечалось, некоторые из предыдущих плакатов end() - один за конечным элементом. Если вам нужно получить доступ к последнему элементу через итераторы, используйте iter = container.end() - 1; В противном случае, в случае векторов, variable = someVector.back(); Предположим, что эта переменная относится к типу данных someVector.

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

Всякий раз, когда размер контейнера изменяется, он будет отслеживать, где находится конец, и будет обновлен до того, как вы снова получите доступ к end(). Однако в зависимости от контейнера, если у вас есть итератор и каким-то образом его изменить, он может аннулировать итератор и прервать процесс итерации.