Обновляется ли условие завершения цикла for в VС++ 6?
-
23-08-2019 - |
Вопрос
for (int i = 0 ; i < stlVector.size() ; i++)
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
}
Учитывает ли часть условия завершения "stlvector.size ()" stlvector.erase (...) "?Другими словами, обновляется ли stlVector.size() для каждой итерации цикла?Я не могу проверить это прямо сейчас, поэтому я задал вопрос здесь.
Спасибо заранее!
С наилучшими пожеланиями,
Женгтоник
Решение
Чтобы внести ясность: не думайте об этом как о том, что цикл что-то обновляет.Каждый раз, когда условие проверяется (в начале каждого цикла), метод size() вызывается для переменной stlVector и возвращается текущий размер вектора.
Метод стирания() уменьшает размер вектора, поэтому при следующем вызове метода size() возвращаемое значение будет меньше.
Другие советы
Да!
stlVector.size () // is called for evey iteration
Таким образом, для каждого цикла вам придется переоценивать тест «i < stlVector.size ()»!
Да, тест проводится с побочными эффектами для каждой петли.
Цикл for — это всего лишь приятное соглашение: цикл for легко разлагается на цикл while:
for (int i = 0 ; i < stlVector.size() ; i++)
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
}
Становится:
int i = 0 ;
while(i < stlVector.size())
{
if (i == 10)
{
stlVector.erase(stlVector.begin() + 5 )
}
i++;
}
-Адам
Да, это так, но не делайте этого!Если вы хотите удалить элементы из вектора, сделайте это внутри другого цикла.В этом случае вы удаляете элементы после индекса i:ничто не гарантирует, что элемент stlVector[i+5] существует.Если вы удалите i-й элемент из вектора, ваш счетчик будет нарушен, потому что вы можете переходить через элементы, не проверяя их.
Самый безопасный способ сделать это — сохранить ссылки на элементы stlVector, которые вы хотите удалить, в другом векторе, а затем выполнить итерацию по этому вспомогательному вектору, выполнив stlVector.erase(auxVector[i]).
Я ожидаю, что предоставленный вами код - это просто «фантастический код» (как выразился один комментатор), чтобы дать конкретный пример того, что вы пытаетесь сделать.
Однако на всякий случай это не так: цикл, который вы дали, пропустит 12-й элемент (т.е.элемент изначально в stlVector[11]
), потому что при осмотре stlVector[10]
вы удаляете более ранний элемент, в результате чего все последующие элементы перемещаются на одну позицию вперед, но вы все равно увеличиваете i
в конце цикла.Итак, следующая итерация будет рассматривать stlVector[11]
который на самом деле является элементом, который изначально был в stlVector[12]
.Чтобы это исправить, вам необходимо --i
после звонка в erase()
.
Всегда переоценивайте обязательно!
Кроме того, чтобы немного уточнить, поскольку вы спросили, сделано ли это таким образом «в VC++ 6».
«Условие продолжения» пересчитывается в каждом цикле в КАЖДОЙ версии C, C++, C# и Java.
Если какой-либо компилятор не генерирует код, который это делает, он сломан и должен избегать.
Как говорили другие, да, условие переоценивается каждый раз в цикле.Вот почему обычная оптимизация производительности:
int saveSize = someExpensiveComputation();
for (int i = 0 ; i < saveSize ; i++)
{
foo(i);
}
где условие цикла вообще требует больших затрат для вычисления, а не
for (int i = 0 ; i < someExpensiveComputation(); i++)
{
foo(i);
}
Где дорогостоящие вычисления без необходимости выполняются на каждой итерации цикла.
Да, это уменьшает размер.Дополнительная информация здесь