Возможный дубликат:
Почему итераторы использования вместо индексов массива?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
а не индекс?Спасибо.
Индекс может использоваться только для контейнеров, поддерживающих случайный доступ - прямой доступ к заданной позиции.
Итератор предлагает унифицированный способ доступа к любой структуре коллекции/данных. Гибкость при рефакторинге кода огромна.
.Предполагаю, что еще одна причина, по которой итераторы следует отдавать предпочтение индексам, заключается в том, что не все коллекции поддерживают постоянный случайный доступ.
Например, если вы хотите, чтобы n-элемент в связанном списке, вам необходимо пройти все предыдущие элементы (с индексами 0...n-1) до тех пор, пока вы не доберетесь до n-элемента. (Эта операция занимает линейное время.)
Итератор (последовательный) запоминает, где он находится в коллекции, и не всегда должен начинаться заново с начала, когда Вам нужен следующий элемент. В вашем примере, на самом деле, нет необходимости обращаться к символам в строке в случайном порядке, а только последовательно, так что использование итератора почти наверняка будет быстрее (константное время)
.Итераторы - стандартный интерфейс. Используя итераторы, можно использовать одни и те же алгоритмы с разными контейнерами. Окончательное решение о том, использовать их или нет, зависит от удобства использования и читаемости.
Например, использование стандартного алгоритма преобразования для сокрытия std::string
в верхний регистр:
std::string str = "A String";
std::transform(str.begin(), str.end(), str.begin(), ::toupper);
приведет к тому, что str
будет равно "A STRING"
.
Для std::string я бы предложил использовать индексы, так как он поддерживает случайный доступ и проще. Единственная причина, по которой "рекомендуется" использовать итераторы, заключается в том, что итераторы предлагают стандартный интерфейс для доступа к последовательностям таким образом, что если, например, ваша последовательность изменится на std::list, то код вашей итерации останется неизменным
.Как сказано в этом вопросе, метод size() не гарантирован O(1)
. В случаях, когда вы не знаете, над каким классом вы проводите итерацию (потому что это аргумент шаблона), вы должны использовать итератор, потому что не каждый класс, который предоставляет итератор, также предоставляет []
(и не каждый класс, который предоставляет []
, предоставляет класс, который работает во времени O(1)). Таким образом, используя итератор, вы убедитесь, что функция будет работать с как можно большим количеством классов (хотя и не с массивами C).
В данном конкретном случае я не вижу причин отдавать предпочтение одному классу перед другим, за исключением личных предпочтений или, возможно, преждевременной оптимизации.
.Итераторы более безопасны и обеспечивают большую гибкость, так как размещены кем-то другим. В добавлении индекс может быть использован только для контейнеров, которые (эффективно) поддерживают случайные доступ (т.е. прямой доступ к элементу в заданной позиции). Итератор - это более общая концепция. Итераторы предлагают эффективный обход связанных списков, файлов и ряда других структур данных. Часто это приводит к генерации более эффективного кода .
.В C++ можно делать много разных вещей. Это еще один пример. В данном случае нет никакой разницы, какой метод использовать. Но в целом итераторы быстрее, безопаснее и обеспечивают большую гибкость при работе с разными типами контейнеров.
.Дубликат:
Тем не менее, это вопрос генерации. Вы можете сделать лот больше с итераторами, используя STL, чем с доступом к массивам. Также, если вам нужен код рефактора, а строку поменять на вектор, список или веревку, то вам вообще не придется переписывать свой код.
Наконец, есть вопрос безопасности в итерации. Если вы хотите получить доступ к символу NEXT в вашем цикле, то с итераторами это можно сделать безопасно, но увеличение подскрипта массива может привести к сегментации на последнем элементе, следовательно, потребуется еще одна проверка
.Оба работает.
Основной причиной будет последовательность: вы одинаково итерацируете над коллекцией или символами строки, запрашивая итератор и делая его вперед.
Не скажу, что стоит упомянуть подробности реализации ++it
, приводящей к увеличению указателя по сравнению с str[i]
с использованием арифметики с указателями. А проверка диапазона также является детализацией реализации