Продвинуть итератор для оператора std::vector std:: advance VS +?

Я обнаружил, что много писал:

int location =2;
vector<int> vec;
vector<int>::iterator it=vec.begin();

/..../
std::advance(it, location);

вместо

 it= it + 5;

Каков предпочтительный/рекомендуемый способ?

Ответ 1

Добавление будет работать только с итераторами с произвольным доступом. std :: advance будет работать со всеми видами итераторов. Пока вы имеете дело только с итераторами в векторах, это не имеет никакого значения, но std :: advance сохраняет ваш код более универсальным (например, вы можете заменить список вектором, и эта часть будет работать).

Для тех, кому это небезразлично, стандарт описывает advance и distance следующим образом (§24.3.4/1):

Так как только итераторы с произвольным доступом предоставляют операторы + и -, библиотека предоставляет два шаблона функций для advance и distance. Эти шаблоны функций используют + и - для итераторов произвольного доступа (и, следовательно, имеют для них постоянное время); для входных, прямых и двунаправленных итераторов они используют ++ для обеспечения реализации линейного времени.

Ответ 2

Это зависит от того, что вам нужно:

Если вам нужна общая, используйте std::advance(it,2). Если кто-то приходит и меняет ваш std::vector на std::list, код все равно будет компилироваться, хотя наступление теперь требует линейного времени вместо постоянного времени.

Если вам нужна производительность, используйте it+=2. Если кто-то приходит и меняет ваш std::vector на std::list, код не будет компилироваться, указывая (возможно, с полезным комментарием) на серьезную проблему с производительностью.

Ответ 3

Это зависит от итератора. it=it+5 работает быстрее, если поддерживается (поддерживается только для итераторов произвольного доступа). Если вы хотите продвинуть менее эффективный итератор (например, форвардный итератор или двунаправленный итератор), вы можете использовать std::advance, но он медленнее, потому что он фактически просматривает все промежуточные элементы.

Ответ 4

std::advance работает также и для неслучайных итераторов, а версия += работает над последовательностями произвольного доступа (векторы и т.п.).

Ответ 5

std::adnvance является общим - полезно, если вы не всегда знаете тип базового контейнера - он работает во всех случаях.

Однако он эффективен: std::advance будет делать оптимизацию, если он передал RandomAccessIterator (например, один из std::vector) и увеличит итератор в цикле для ForwardAccessIterator (как один в std::list).

Ответ 6

Используйте std:: advance. Он так же эффективен (он использует итераторные черты, чтобы просто добавлять итератор для итераторов произвольного доступа), и является более общим в том, что он работает и с другими типами итераторов.

Ответ 7

Если вы никогда не собираетесь менять контейнер (а вы, вероятно, нет), используйте +, потому что он легко видит и понимает и оставляет код менее загроможденным.

Если вы считаете, что хотите изменить контейнер, или если вы работаете внутри шаблона, который может быть создан в разных типах контейнеров, используйте заранее, потому что он работает с чем-либо.

Как правило, я не беспокоюсь об изменении типов контейнеров, потому что обнаружил, что когда мне нужно изменить тип контейнера, я в конечном итоге пересматриваю везде, где используется контейнер, просто чтобы быть уверенным, m не делает ничего, что внезапно глупо (например, случайно выщипывая элементы из середины списка).