Векторные итераторы <or! =
Может ли кто-нибудь помочь мне понять, есть ли большая разница в !=
И <
когда речь заходит о векторных итераторах в цикле for
?
Я имею в виду, независимо от того, используете ли вы !=
И <
, результат должен быть таким же?
for (vector<int>::iterator i = vec.begin(); i != vec.end(); i++)
// DO STUFF
for (vector<int>::iterator i = vec.begin(); i < vec.end(); i++)
// DO STUFF
Я знаю, что наиболее распространенным способом является использование !=
, Но будет ли <
большая проблема при использовании?
Ответы
Ответ 1
operator<
поддерживается только для итераторов произвольного доступа. std::vector::iterator
- это std::vector::iterator
с произвольным доступом, поэтому оба i != vec.end()
и i < vec.end()
поддерживаются и действительны и не имеют никакого значения в вашем примере.
Если у вас есть контейнер, который не поддерживает итераторы с произвольным доступом (например, std::list
), i < list.end()
не будет компилироваться.
Общая рекомендация состоит в том, чтобы использовать приращение постфикса только тогда, когда это необходимо, хотя из-за того, что он может создать ненужную копию, когда итератор является нетривиальным, поэтому ++i
является более чистым и может быть быстрее.
Кроме того, если цикл вызывает функцию, определение которой недоступно в этом модуле трансляции, vec.end()
будет перезагружаться из памяти на каждой итерации цикла, что может привести к ненужной ошибке кеша. Вы можете избежать перезагрузки, сохранив значение в локальной переменной, чтобы компилятор был уверен, что локальная переменная недоступна для любой другой функции:
for(vector<int>::iterator i = vec.begin(), j = vec.end(); i < j; ++i)
// ...
Еще лучше, вы можете использовать циклы диапазона, которые избегают этих ошибок производительности для вас:
for(auto const& elem : vec)
// ...
Ответ 2
Вся философия, стоящая за частью STL
стандартной библиотеки (контейнеры, итераторы и алгоритмы), заключается в минимизации программных различий между контейнерами. Они демонстрируют разные свойства, но как вы их программируете, должны быть как можно более похожими.
Это упрощает обучение и упрощает использование в целом. Это означает, что вы можете написать одну общую функцию (или алгоритм) и применить ее к любому другому контейнеру (или как можно больше).
Имея это в виду, полезно использовать синтаксис, который является общим для всех контейнеров и итераторов, где это возможно.
Только итераторы некоторых контейнеров позволяют принимать итераторы <
сравнения, но все контейнеры !=
. По этой причине я бы рекомендовал всегда использовать !=
качестве последовательности и облегчить перенос кода в другой контейнер.
Ответ 3
Это имеет значение, хотя и не для std::vector
. Все итераторы равны друг другу, поэтому !=
Всегда будет работать. Итераторы с произвольным доступом менее сопоставимы, как и std::vector
, поэтому в вашем случае это не будет большой проблемой.