Обновляется ли условие завершения цикла for в VC ++ 6? - PullRequest
0 голосов
/ 12 февраля 2009
for (int i = 0 ; i < stlVector.size() ; i++)
{ 
    if (i == 10)
    { 
        stlVector.erase(stlVector.begin() + 5 )
    }
}

Принимает ли часть условия завершения "stlVector.size ()" значение "stlVector.erase (...)" во внимание? Другими словами, обновляется ли stlVector.size () для каждой итерации цикла? Я не могу проверить это прямо сейчас, поэтому я разместил вопрос здесь.

Спасибо заранее!

С уважением,

zhengtonic

Ответы [ 9 ]

5 голосов
/ 12 февраля 2009

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

Метод erase () уменьшает размер вектора, поэтому при следующем вызове size () возвращаемое значение будет меньше.

4 голосов
/ 12 февраля 2009

Да, тест проводится с побочными эффектами для каждой петли.

Цикл 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++;
}

-Adam

4 голосов
/ 12 февраля 2009

Да, это так!

stlVector.size () // is called for evey iteration

Таким образом, для каждого цикла у вас будет повторная оценка теста "i <stlVector.size ()"

2 голосов
/ 14 февраля 2009

Всегда переоценивай обязательно!

2 голосов
/ 13 февраля 2009

Полагаю, что предоставленный вами код - это просто "код фантазии" (как сказал один из комментаторов), чтобы дать конкретный пример того, что вы пытаетесь сделать.

Однако на всякий случай это не так: цикл, который вы дали, пропустит 12-й элемент (т.е. элемент, изначально в stlVector[11]), потому что при проверке stlVector[10] вы удаляете более ранний элемент, вызывая последующие элементы шунтируют вперед на одну позицию, но вы все равно увеличиваете i в конце цикла. Таким образом, следующая итерация будет смотреть на stlVector[11], который на самом деле является элементом, который изначально был в stlVector[12]. Чтобы исправить это, вам нужно --i после звонка на erase().

2 голосов
/ 12 февраля 2009

Да, это так, но не делайте этого! Если вы хотите удалить элементы из вектора, сделайте это внутри другого цикла. В этом случае вы удаляете элементы после индекса i: ничто не гарантирует существования элемента stlVector [i + 5]. Если вы удалите i-й элемент из вектора, ваш счет нарушится, потому что вы можете переходить по элементам, не проверяя их.

Самый безопасный способ сделать это - сохранить ссылки для элементов в stlVector, который вы хотите удалить в другом векторе, а затем выполнить итерации для этого вспомогательного вектора, выполнив stlVector.erase (auxVector [i]).

1 голос
/ 12 февраля 2009

Как уже говорили другие, да, условие пересматривается каждый раз через цикл. Вот почему общая оптимизация производительности:

int saveSize = someExpensiveComputation();

for (int i = 0 ; i < saveSize ; i++)
{ 
    foo(i);
}

, где условный цикл вообще дорог для вычисления, вместо

for (int i = 0 ; i < someExpensiveComputation(); i++)
{ 
    foo(i);
}

Там, где дорогостоящие вычисления без необходимости выполняются на каждой итерации цикла.

1 голос
/ 12 февраля 2009

Также, чтобы уточнить немного, так как вы спросили, сделано ли это так "в VC ++ 6".

«Условие продолжения» переоценивается в каждом цикле в КАЖДОЙ версии C, C ++, C # и Java.

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

0 голосов
/ 12 февраля 2009

Да, это уменьшает размер. Больше информации здесь

...