2009-02-12 2 views
0
for (int i = 0 ; i < stlVector.size() ; i++) 
{ 
    if (i == 10) 
    { 
     stlVector.erase(stlVector.begin() + 5) 
    } 
} 

Содержит ли условие термина «stlVector.size()« принять »stlVector.erase (...)« ? Другими словами, stlVector.size() обновляется для каждой итерации цикла? Я не могу проверить это прямо сейчас, поэтому я разместил здесь вопрос.Выполняется ли условие завершения цикла «для цикла» в VC++ 6?

Thx заранее!

С наилучшими пожеланиями,

zhengtonic

+0

почти оскорбительный комментарий! – claf

+0

Привет, Исмаил, ты прав, я мог просто запустить отладчик, но я был в полете, и у меня не было компьютера с VC++. Скачивая материал, он очень дорог, и я не знал, имел ли в отеле доступ в Интернет. Хотел разобраться в этом, пока у меня был доступ в Интернет, поэтому я могу спокойно спать. – zhengtonic

ответ

5

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

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

4

Да, это делает!

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

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

4

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

для цикла просто хорошая конвенция - это цикл легко раскладывается как время цикла:

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

+0

Стоит упомянуть здесь, что существует небольшая разница в сфере видимости - '' '' int i''' доступен после цикла в примере '' 'while''', тогда как он ограничен областью цикла в' '' for Пример '' '. – Riot

0

Да это уменьшает размер. Дополнительная информация here

2

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

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

+0

На самом деле, если вы прочтете его снова: он не стирает i + 5: th элемент. И я считаю, что проверка «if (i == 10)» (вместе с условием цикла) в основном гарантирует, что элемент begin() + 5 существует, нет? Более того, не использует итераторы, превосходящие вспомогательное векторное решение, которое вы предлагаете? – Reunanen

+0

Вы имеете право на проверку элементов и использование итераторов. Я думал, что этот пример был просто «фэнтезийным кодом» и только хотел указать на общую ошибку (используя индекс, указывающий на элемент в векторе, который был изменен внутри цикла). – jfsantos

1

Кроме того, чтобы немного разъяснить, так как вы спросили, сделано ли это так «в VC++ 6».

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

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

+0

VC++ 6 уже сломан :) –

+0

Да, VC++ 6 определенно сломан. Я не могу сказать, нарушилось ли это таким образом, но это, безусловно, нарушено бесчисленными другими способами. – jalf

+0

Я просто подумал ... Может быть, OP действительно знает все это и просто невероятно саркастично? :) Может быть, его следующий вопрос будет: «Есть ли 2 + 2 == 4 в VC++ 6?» :-P –

1

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

int saveSize = someExpensiveComputation(); 

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

где цикл условно вовсе дорого вычислить, вместо

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

Где дорогостоящая вычисление понапрасну сделано каждой итерации цикла.

+0

, на самом деле это не будет делать что-то более быстрое на достойном компиляторе. поскольку размер() равен O (1) в std :: vector (стандарт говорит так). Вызов будет вставлен в линию, и местоположение векторного объекта не изменится в середине цикла. Таким образом, вы торгуете одним номером памяти для другого ... –

+0

Если вы проверите его, вы обнаружите, что сгенерированная сборка обычно идентична (или эквивалентна по функциональности). –

+0

да, поэтому я сказал: «где условие цикла вообще дорогой для вычисления ». Я не хотел полностью переписывать его пример, чтобы выразить свою точку зрения. – PhysicalEd

2

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

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

Смежные вопросы