Кэширование конечного итератора - Хорошая идея или Плохая Идея?

Вообще говоря, действительно ли это - хорошая идея кэшировать конечный итератор (конкретно контейнеры STL) в целях эффективности и скорости? такой как в следующем бите кода:

std::vector<int> vint;
const std::vector<int>::const_iterator end = vint.end();
std::vector<int>::iterator it = vint.begin();

while (it != end)
{
   ....
   ++it;
}

При каких условиях конец оценил бы делаться недействительным? был бы, стираясь от контейнерного конца причины, который будет делаться недействительным во всех контейнерах STL или просто некоторых?

18
задан Hippicoder 21 June 2010 в 11:15
поделиться

7 ответов

В простом случае вектора итератор end изменится при добавлении или удалении элементов из контейнера; однако обычно безопаснее предположить, что если вы изменяете контейнер во время итерации по нему, все итераторы для него станут недействительными. Итераторы могут быть реализованы по-разному в любой данной реализации STL.

Что касается кеширования итератора end - его, безусловно, можно кэшировать, но чтобы узнать, действительно ли он быстрее в вашем случае, лучше всего профилировать свой код и посмотреть . Хотя получение итератора end из вектора , вероятно, является быстрой реализацией с недавней библиотекой и компилятором STL, я работал над прошлыми проектами, в которых кэширование ] end итератор дал нам значительный прирост скорости. (Это было на PlayStation 2, так что отнеситесь к этому с недоверием.)

15
ответ дан 30 November 2019 в 08:21
поделиться

Если мы говорим об эффективности и скорости: кэширование конечного итератора не требуется из-за оптимизации компилятора и встраивания.

4
ответ дан 30 November 2019 в 08:21
поделиться

В общем, хорошая идея для кеширования конечного итератора (в частности, Контейнеры STL) для повышения эффективности и скорости?

Если вы используете алгоритмы контейнера STL, кеширование конечного итератора происходит в любом случае (когда вы передаете результат container.end () в качестве параметра).

Если вы изменяете память контейнера (вставляете / удаляете элементы), это плохая идея.

Кроме того, кеширование для повышения эффективности редко имеет смысл: в большинстве случаев end () встроен компилятором, а когда это не так, очень вероятно, что ваша эффективность не зависит от результата end (), поскольку кешировано. YMMV хотя.

2
ответ дан 30 November 2019 в 08:21
поделиться

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

1
ответ дан 30 November 2019 в 08:21
поделиться

Я часто использую этот стиль для итерации контейнеров:

// typedef std::vector<Person> Persons;
Persons::iterator it = persons.begin(), end = persons.end();
for (; it != end; ++it)
{
    Person & person = *it;
    // ...
}

Удаление элемента из вектора делает недействительными все итераторы после стертой позиции.

Я не уверен насчет других типов контейнеров. В любом случае, я думаю, было бы безопасно предположить, что все итераторы станут недействительными после стирания. Если вам действительно нужна очень конкретная информация, вы всегда можете ее найти. Мне это редко нужно из-за моего довольно консервативного стиля программирования.

1
ответ дан 30 November 2019 в 08:21
поделиться

Правила признания недействительными (для итераторов) определены очень явно для каждого типа контейнера. Я считаю сайт SGI очень полезным http://www.sgi.com/tech/stl/table_of_contents.html

Специально для векторов, которые я нахожу:

[5] Итераторы вектора становятся недействительными, когда его память перераспределяется. Кроме того, вставка или удаление элемента в середине вектора делает недействительными все итераторы, которые указывают на элементы, следующие за точкой вставки или удаления. Отсюда следует, что вы можете предотвратить аннулирование итераторов вектора, если вы используете функцию Reserve () для предварительного выделения такого объема памяти, который будет когда-либо использоваться вектором, и если все вставки и удаления находятся в конце вектора.

2
ответ дан 30 November 2019 в 08:21
поделиться

Стирание из контейнера, над которым вы в данный момент выполняете итерацию, всегда является плохой идеей. Фактическое кэширование вашего конечного итератора не изменит этого.

h.

2
ответ дан 30 November 2019 в 08:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: