Здравствуйте Anton V. Kolotaev, Вы писали:
AVK>Например, сначала очистить от нулевых элементов, а потом сделать пользу.
AVK>ИМХО ты намудрил.
AVK>приведи пример, где такой continue все портит.
Первое, что нашлось.
for (CallbacksTimeIndex::HardLowTimeIndex::TIndex::iterator it = pt->callbacks_time_index.hard_low_time_index.index.begin(), nit = it;
it != pt->callbacks_time_index.hard_low_time_index.index.end(); it = nit)
{
nit++;
CallbackInfo callback = it->second->second;
if (callback.low_time > cur_time)
break;
#ifdef _TRACE_HARD_QUERIES_
DBG (CFormatString("Time: %t") << CoFileTimeNow());
#endif
Items::Items::iterator fit = pt->items.items.find (callback.item_handle);
if (fit == pt->items.items.end())
continue;
bool is_readed = false;
ValueInfo & value = pt->items_cash[fit->second.kind];
if ((value.quality & QUALITY_MASK) != QUALITY_BAD)
{
LONGLONG dtime = cur_time - FileTime2LongLong (value.time);
if (2 * dtime < callback.period)
is_readed = true;
}
if (is_readed)
{
pt->UpdateQuery (it, value);
}
else
{
qmap[Kind2Kind(fit->second.kind)] = MapValue();
}
}
удаление элемента происходит в функции 'pt->UpdateQuery'.
P.S. Вот еще одна нехорошость твоего цикла, erase нужно обязательно вызывать из самого цикла, а часто хочется вынести удаление элемента в отдельную функцию...
DG>А как уважаемый All пишет цикл по Stl-ной коллекции, если во время этого самого цикла нужна возможность удаления текущего элемента?
DG>Т.е. что-то такое: DG>
DG>for (std::list<int>::iterator it = items.begin(); it != items.end(); ++it)
DG>{
DG> if (*it == 0)
DG> erase (it); //это есть неправильно.
DG>}
DG>
DG>Сейчас пишу так: DG>
DG>for (std::list<int>::iterator it = items.begin(), nit; it != items.end(); it = nit)
DG>{
DG> nit = it; ++nit;
DG> if (*it == 0)
DG> erase (it);
DG>}
DG>
DG>Как еще можно такие циклы писать?
Может так подойдет?
std::list<int*> aCont;
...
std::list<int*>::iterator it = aCont.begin();
while(it != aCont.end())
{
if(!(*it))
it = aCont.erase(it);
else
++it;
}
Любите книгу — источник знаний (с) М.Горький
Re[6]: Цикл по Stl-коллекции, если нужно удаление
От:
Аноним
Дата:
24.07.02 06:15
Оценка:
Здравствуйте Anton V. Kolotaev, Вы писали:
AVK>Здравствуйте DarkGray,
AVK>Сложный случай.
AVK>Вариант с nit — по-моему, лучшее, что можно придумать.
Для list согласен. А будет ли этот цикл корректно работать с vector? Как я себе представляю, при erase все последующие элементы должны сдвигаться.
Здравствуйте Аноним, Вы писали:
AVK>>Вариант с nit — по-моему, лучшее, что можно придумать.
А>Для list согласен. А будет ли этот цикл корректно работать с vector? Как я себе представляю, при erase все последующие элементы должны сдвигаться.
Для вектора, конечно, корректно работать не будет
Но для вектора лучше использовать вот такой цикл:
std::vector<int> vec;
for (int i = vec.size() - 1; i >= 0; --i)
{
vec::iterator it = std::advance (vec.begin(), i);
if (*it == 0)
std::erase(it);
}
std::list <int> List;
...
list <int>::iterator Iter = List.begin ();
while ( Iter != List.end () )
List.erase ( Iter++ );
Для for'a можно немного переделать.
Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным :-).
Good luck
Здравствуйте Аноним, Вы писали:
А>Для for'a можно немного переделать. А>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным . А>Good luck
Super! А оценку негде поставить...
Re[3]: Цикл по Stl-коллекции, если нужно удаление
От:
Аноним
Дата:
24.07.02 10:00
Оценка:
Здравствуйте Anton V. Kolotaev, Вы писали:
AVK>Здравствуйте Аноним, Вы писали:
А>>Для for'a можно немного переделать. А>>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным :-). А>>Good luck
AVK>Super! А оценку негде поставить... :(
Ставь. Я запомню :-)))
Здравствуйте DarkGray, Вы писали:
DG>Здравствуйте Аноним, Вы писали:
AVK>>>Вариант с nit — по-моему, лучшее, что можно придумать.
А>>Для list согласен. А будет ли этот цикл корректно работать с vector? Как я себе представляю, при erase все последующие элементы должны сдвигаться.
DG>Для вектора, конечно, корректно работать не будет
DG>Но для вектора лучше использовать вот такой цикл: DG>
DG>std::vector<int> vec;
DG>for (int i = vec.size() - 1; i >= 0; --i)
DG>{
DG> vec::iterator it = std::advance (vec.begin(), i);
DG> if (*it == 0)
DG> std::erase(it);
DG>}
DG>
Я бы для вектора несколько по-другому сделал: копирование в любом случае нужно, а чтобы кучу раз не перемещать массив в памяти, просто скопировать нужные элементы в новый массив например:
int newsize = v.size();
for (vector<>::iterator i = v.begin(); i < v.size(); i++)
if (*i == 0 ) newsize-- ; //этот элемент мы не скопируем
vector<> v2; v2.reserve(newsize); //только резервируем местоfor (vector<>::iterator i = v.begin(); i < v.size(); i++)
if (*i != 0 )
v2.push_back(*i)
v.swap(v2); //swap не выполнит копирования
//здесь v2 выйдет за область видимости и уничтожится.
Здравствуйте Аноним, Вы писали:
А>>>Для for'a можно немного переделать. А>>>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным . А>>>Good luck
AVK>>Super! А оценку негде поставить... А>Ставь. Я запомню
дык — куда тебе ставить то =) — регься.
Здравствуйте Аноним, Вы писали:
А>Здравствуйте DarkGray, Вы писали:
А>
А> std::list <int> List;
А> ...
А> list <int>::iterator Iter = List.begin ();
А> while ( Iter != List.end () )
А> List.erase ( Iter++ );
А>
А>Для for'a можно немного переделать. А>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным . А>Good luck
Я вот хочу немножко завистливо попридираться (Так просто для иллюстрации того факта, что придраться всегда есть к чему)
Надо сказать, что это хоть и очень надежная, но все-таки завязка на особенность конкретной реализации (или даже всех конкретных реалиаций ). Описанный тобой алгоритм работы постинкремента относится только к перегруженному постинкременту, но не ко встроенному постинкременту. Таким образом, если вдруг каким-то образом окажется, что итератор контейнера 'std::list<int>' является скалярным типом, то все, что ты сказал о постинкременте не будет соответствовать действительности.
Нет, я не могу с ходу представить, как можно релизовать итератор контейнера 'std::list<int>' скалярным типом. Да и не нужно это никому. Но такая вот чисто теоретическая придирка к твоему коду может иметь место.
Здравствуйте Андрей Тарасевич, Вы писали:
АТ>Я вот хочу немножко завистливо попридираться (Так просто для иллюстрации того факта, что придраться всегда есть к чему) :))
АТ>Надо сказать, что это хоть и очень надежная, но все-таки завязка на особенность конкретной реализации (или даже всех конкретных реалиаций :) ). Описанный тобой алгоритм работы постинкремента относится только к перегруженному постинкременту, но не ко встроенному постинкременту. Таким образом, если вдруг каким-то образом окажется, что итератор контейнера 'std::list<int>' является скалярным типом, то все, что ты сказал о постинкременте не будет соответствовать действительности.
Если я не ошибаюсь, префиксный operator++() отличается от постфиксного operator++(int) именно тем, что префиксный возвращает уже увеличенное значение, а постфиксный — копию текущего значения.
(Извиняюсь за корявость высказывания, но надеюсь, меня все поняли ;-)). Это справедливо и для скалярных типов. (standard, 5.2.6 , 5.3.2)
То есть я хотел сказать, что такое поведение постфиксного operator++ (int) обусловлено стандартом
Здравствуйте santucco, Вы писали:
S>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>Я вот хочу немножко завистливо попридираться (Так просто для иллюстрации того факта, что придраться всегда есть к чему)
АТ>>Надо сказать, что это хоть и очень надежная, но все-таки завязка на особенность конкретной реализации (или даже всех конкретных реалиаций ). Описанный тобой алгоритм работы постинкремента относится только к перегруженному постинкременту, но не ко встроенному постинкременту. Таким образом, если вдруг каким-то образом окажется, что итератор контейнера 'std::list<int>' является скалярным типом, то все, что ты сказал о постинкременте не будет соответствовать действительности.
S>Если я не ошибаюсь, префиксный operator++() отличается от постфиксного operator++(int) именно тем, что префиксный возвращает уже увеличенное значение, а постфиксный — копию текущего значения. S>(Извиняюсь за корявость высказывания, но надеюсь, меня все поняли ). Это справедливо и для скалярных типов. (standard, 5.2.6 , 5.3.2) S>То есть я хотел сказать, что такое поведение постфиксного operator++ (int) обусловлено стандартом
S>
Э нет, мсье Тарасевич прав, тут есть где развернуться буквоеду! Гы-гы!
S>>>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным .
В том-то и дело, что для неперегруженного постинкремента копия может и не делаться (т. е., например, для int это, по всей вероятности, будет просто ассемблерная инструкция инкремента, вставленная после использования).
Здравствуйте achp, Вы писали:
A>Здравствуйте santucco, Вы писали:
S>>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>>Я вот хочу немножко завистливо попридираться (Так просто для иллюстрации того факта, что придраться всегда есть к чему) :))
АТ>>>Надо сказать, что это хоть и очень надежная, но все-таки завязка на особенность конкретной реализации (или даже всех конкретных реалиаций :) ). Описанный тобой алгоритм работы постинкремента относится только к перегруженному постинкременту, но не ко встроенному постинкременту. Таким образом, если вдруг каким-то образом окажется, что итератор контейнера 'std::list<int>' является скалярным типом, то все, что ты сказал о постинкременте не будет соответствовать действительности.
S>>Если я не ошибаюсь, префиксный operator++() отличается от постфиксного operator++(int) именно тем, что префиксный возвращает уже увеличенное значение, а постфиксный — копию текущего значения. S>>(Извиняюсь за корявость высказывания, но надеюсь, меня все поняли ;-)). Это справедливо и для скалярных типов. (standard, 5.2.6 , 5.3.2) S>>То есть я хотел сказать, что такое поведение постфиксного operator++ (int) обусловлено стандартом
S>> :)))
A>Э нет, мсье Тарасевич прав, тут есть где развернуться буквоеду! Гы-гы!
S>>>>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным :-).
A>В том-то и дело, что для неперегруженного постинкремента копия может и не делаться (т. е., например, для int это, по всей вероятности, будет просто ассемблерная инструкция инкремента, вставленная после использования).
operator++
Цитирую: The value obtained by applying a postfix ++ is a value that the operand had before applying the operator [Note: the value obtained is a copy of the original value]
Насчет ассемблера —
int main ()
{
int A = 0;
int B = 0;
B = A++;
return 0;
}
вот дезассемблированный кусок с коментариями
// инициализация A
0x8048556 <main+6>: mov DWORD PTR [ebp-4],0x0
// инициализация B
0x804855d <main+13>: mov DWORD PTR [ebp-8],0x0
// делается копия A в eax
0x8048564 <main+20>: mov eax,DWORD PTR [ebp-4]
// содержимое eax записывается в B
0x8048567 <main+23>: mov DWORD PTR [ebp-8],eax
// инкрементируется A
0x804856a <main+26>: inc DWORD PTR [ebp-4]
Здравствуйте santucco, Вы писали:
S>Здравствуйте achp, Вы писали:
A>>Здравствуйте santucco, Вы писали:
S>>>Здравствуйте Андрей Тарасевич, Вы писали:
АТ>>>>Я вот хочу немножко завистливо попридираться (Так просто для иллюстрации того факта, что придраться всегда есть к чему)
АТ>>>>Надо сказать, что это хоть и очень надежная, но все-таки завязка на особенность конкретной реализации (или даже всех конкретных реалиаций ). Описанный тобой алгоритм работы постинкремента относится только к перегруженному постинкременту, но не ко встроенному постинкременту. Таким образом, если вдруг каким-то образом окажется, что итератор контейнера 'std::list<int>' является скалярным типом, то все, что ты сказал о постинкременте не будет соответствовать действительности.
S>>>Если я не ошибаюсь, префиксный operator++() отличается от постфиксного operator++(int) именно тем, что префиксный возвращает уже увеличенное значение, а постфиксный — копию текущего значения. S>>>(Извиняюсь за корявость высказывания, но надеюсь, меня все поняли ). Это справедливо и для скалярных типов. (standard, 5.2.6 , 5.3.2) S>>>То есть я хотел сказать, что такое поведение постфиксного operator++ (int) обусловлено стандартом
S>>>
A>>Э нет, мсье Тарасевич прав, тут есть где развернуться буквоеду! Гы-гы!
S>>>>>Весь фокус в том, что постинкрементный operator++ ДЕЛАЕТ КОПИЮ текущего итератора, увеличивает текущий итератор и возвращает сохраненную копию. Таким образом, текущий итератор остается валидным .
A>>В том-то и дело, что для неперегруженного постинкремента копия может и не делаться (т. е., например, для int это, по всей вероятности, будет просто ассемблерная инструкция инкремента, вставленная после использования).
S>operator++ S>Цитирую: The value obtained by applying a postfix ++ is a value that the operand had before applying the operator [Note: the value obtained is a copy of the original value] S>Насчет ассемблера — S>
S>int main ()
S>{
S> int A = 0;
S> int B = 0;
S> B = A++;
S> return 0;
S>}
S>
S>вот дезассемблированный кусок с коментариями S>
S>// инициализация A
S>0x8048556 <main+6>: mov DWORD PTR [ebp-4],0x0
S>// инициализация B
S>0x804855d <main+13>: mov DWORD PTR [ebp-8],0x0
S>// делается копия A в eax
S>0x8048564 <main+20>: mov eax,DWORD PTR [ebp-4]
S>// содержимое eax записывается в B
S>0x8048567 <main+23>: mov DWORD PTR [ebp-8],eax
S>// инкрементируется A
S>0x804856a <main+26>: inc DWORD PTR [ebp-4]
S>
S>
Ну и?
PS. Вообще, это такая дребедень — про побочные эффекты выражений и точки следования; лучше о них не задумываться, а то голова треснет!