Зачем использовать string:: iterator вместо индекса?
Возможный дубликат:
Зачем использовать итераторы вместо индексов массива?
string::iterator it;
for (it = str.begin(); it < str.end(); it++)
cout << *it;
cout << endl;
Почему бы и нет:
for (int i = 0; i < str.size(); i++)
cout << str[i];
cout << endl;
Кажется, что string:: iterator не предоставляет проверку диапазона. Почему мы должны использовать string::iterator
вместо индекса?
Спасибо.
Ответы
Ответ 1
Индекс может использоваться только для контейнеров, поддерживающих произвольный доступ - прямой доступ к данной позиции.
Итератор предлагает унифицированный способ доступа к любой коллекции/структуре данных. Гибкость при рефакторинге вашего кода огромна.
Ответ 2
Итераторы - это стандартный интерфейс. Используя итераторы, вы можете использовать одни и те же алгоритмы с разными контейнерами. Окончательное решение о том, использовать их или нет, зависит от вас на основе удобства и удобочитаемости.
Например, используя стандартный алгоритм преобразования для скрытого std::string
в верхний регистр:
std::string str = "A String";
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
приведет к тому, что str
будет равно "A STRING"
.
Ответ 3
Для std::string в частности, я бы предложил вам использовать индексы, поскольку он поддерживает Random Access и его более простой способ. Единственная причина, по которой его "рекомендуется" использовать итераторы, состоит в том, что итераторы предлагают стандартный интерфейс для доступа к последовательностям, так что если ваша последовательность была изменена на std:: list, например, ваш итерационный код остался бы без изменений
Ответ 4
Дубликат:
Тем не менее, это вопрос общности. Вы можете сделать гораздо больше с итераторами, использующими STL, чем с доступом к массиву. Кроме того, если вам нужен код рефакторинга и изменить строку на вектор, список или rope, вам не придется переписывать код на всех.
Наконец, вопрос безопасности в итерации. Если вы хотите получить доступ к символу NEXT в, с помощью итераторов, вы можете сделать это безопасно, но увеличение индекса массива может наступить на вас в последнем элементе, поэтому потребуется еще одна проверка.
Ответ 5
Как указано в этом вопросе, метод size() не гарантированно будет O (1)
Ответ 6
В тех случаях, когда вы не знаете, какой класс вы итерируете (потому что это аргумент шаблона), вы должны использовать итератор, потому что не каждый класс, предоставляющий итератор, также предоставляет []
(и не каждый класс, который обеспечивает []
, обеспечивает тот, который работает в O (1) раз). Таким образом, используя итератор, вы убедитесь, что функция будет работать с как можно большим количеством классов (хотя и не с C-массивами).
В этом конкретном случае я не вижу причин предпочитать одно за другим, кроме личных предпочтений или, возможно, преждевременной оптимизации.
Ответ 7
Оба работают.
Основная причина - согласованность: вы итерации по коллекции или символам строки одинаково, запрашивая итератор и заставляя его продвигаться.
Я бы не сказал, что детали реализации ++it
, приводящие к увеличению указателя по сравнению с str[i]
с использованием арифметики указателя, стоит упомянуть. Кроме того, проверка диапазона также представляет собой детали реализации.
Ответ 8
Итераторы более безопасны и обеспечивают большую гибкость, как и кто-то другой. Кроме того, индекс может использоваться только для контейнеров, которые (эффективно) поддерживают random
доступ (т.е. прямой доступ к элементу в заданной позиции). Итератор является более общей концепцией. Итераторы предлагают эффективный обход связанных списков, файлов и ряда других структур данных. Это часто приводит к созданию более эффективного кода.
Ответ 9
Я предполагаю, что еще одна причина, почему итераторы должны быть предпочтительнее по индексам, состоит в том, что не все коллекции поддерживают случайный доступ по постоянному времени.
Например, если вам нужен n-й элемент в связанном списке, вам нужно пройти все предыдущие элементы (с индексами 0..n-1) до тех пор, пока вы не перейдете к n-му элементу. (Эта операция принимает линейное время.)
Итератор (последовательный) запоминает, где он находится в коллекции, и ему не всегда нужно начинать с самого начала, когда вам нужен следующий элемент. В вашем примере вам фактически не нужно обращаться к символам в строке в произвольном порядке, но только последовательно, поэтому использование итератора почти наверняка будет быстрее (постоянное время).
Ответ 10
В С++ вы можете делать много вещей разными способами. Это еще один пример.
В этом случае нет разницы, какой метод использовать. Но в целом итераторы быстрее, безопаснее и обеспечивают большую гибкость в отношении различных типов контейнеров.