Здравствуйте, BlackBox, Вы писали:
BB>Добрый день.
BB>Мне надо в цикле перебирать значения хранящиеся в векторе. При определенном условии я должен удалить текущее знаечение из вектора и продолжить обход.
Здравствуйте, BlackBox, Вы писали:
BB>Легальный ли это код ...
При срабатывании условия при i == 0 получаем невалидный итератор.
BB>...или лучше сделать c remove+erase?
Конечно.
Здравствуйте, BlackBox, Вы писали:
BB>Добрый день.
BB>Мне надо в цикле перебирать значения хранящиеся в векторе. При определенном условии я должен удалить текущее знаечение из вектора и продолжить обход.
BB>Сейчас сделал так:
Может тогда сделать напрямую, без it
for (int i=0; i != table.size();)
{
...
if (cond)
table.erase(table.begin()+i);
else
++i;
...
}
Насчет remove-erase, наверное лучше.
Еще можно удалять элементы начиная с хвоста
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, BlackBox, Вы писали:
BB>Добрый день.
BB>Мне надо в цикле перебирать значения хранящиеся в векторе. При определенном условии я должен удалить текущее знаечение из вектора и продолжить обход.
BB>Сейчас сделал так:
BB>
BB>...
BB>table_iter_t it = table.begin();
BB>for (int i=0; it != table.end(); it++, i++)
BB>{
BB>...
BB> if (cond)
BB> {
BB> table.erase(it);
BB> i--;
BB> it = table.begin()+i;
BB> continue;
BB> }
BB>...
BB>}
BB>
BB>Легальный ли это код или лучше сделать c remove+erase?
Не совсем если удалишь нулевой элемент потом i-- ...
BB>Заранее спасибо за ответы.
Должно работать:
table_iter_t it = table.begin();
while(it!=table.end){
...
if (cond)
{
table.erase(it);
//Значение итератора остается старым, но указывает на следующий элемент вектораcontinue;
}
++it;
...
}
Здравствуйте, BacCM, Вы писали:
BCM>Должно работать: BCM>
BCM>table_iter_t it = table.begin();
BCM>while(it!=table.end){
BCM> ...
BCM> if (cond)
BCM> {
BCM> table.erase(it);
BCM> //Значение итератора остается старым, но указывает на следующий элемент вектора
BCM> continue;
BCM> }
BCM> ++it;
BCM> ...
BCM>}
BCM>
Нет, не должно. После вызова erase итератор становится невалидным, и все дальнейшие операции с ним ведут к UB.
Однако в случае, когда итератор вектора — обычный указатель, то этот код будет работать, причем правильно. Но если поменяется реализация STL, и в этой реализации вектор будет иметь "полноценные" итераторы, то сюрпризы обеспечены.
Здравствуйте, Bell, Вы писали:
B>Нет, не должно. После вызова erase итератор становится невалидным, и все дальнейшие операции с ним ведут к UB. B>Однако в случае, когда итератор вектора — обычный указатель, то этот код будет работать, причем правильно. Но если поменяется реализация STL, и в этой реализации вектор будет иметь "полноценные" итераторы, то сюрпризы обеспечены.
Теоретически, да, и для полной и абсолютной совместимости так нельзя, но вряд-ли сушествует вариант stl где итератор vector реализован по иному
Здравствуйте, BacCM, Вы писали:
BCM>Теоретически, да, и для полной и абсолютной совместимости так нельзя, но вряд-ли сушествует вариант stl где итератор vector реализован по иному
STLPort с включенным отладочным режимом.
DinkumSTL для VC7.
Здравствуйте, A.Grom, Вы писали:
AG>Зачем так сложно? AG>erase возвращает ближайший валидный итератор, следующий за удалённым значением, или .end() если в контейнере больше ничего нет.
AG>
AG> table_iter_t it = table.begin();
AG> while(it != table.end())
AG> {
AG> if (cond)
AG> it = table.erase(it);
AG> else
AG> ++it;
AG> }
AG>
Здравствуйте, A.Grom, Вы писали:
AG>Конечно, код так выглядит более читаемо, но есть 2 неприятности, большая и маленькая
AG>1. Не всегда удобно условие засовывать в предикат
Тут могут помочь библиотеки типа boost::bind и boost::lambda, но, само собой, иногда явный цикл более выразителен. AG>2. С ассоциативными контейнерами remove_if врядли даст ожидаемый результат
С ассоциативными контейнерами remove_if просто не будет компилиься.
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, A.Grom, Вы писали:
AG>>Конечно, код так выглядит более читаемо, но есть 2 неприятности, большая и маленькая
AG>>1. Не всегда удобно условие засовывать в предикат B>Тут могут помочь библиотеки типа boost::bind и boost::lambda, но, само собой, иногда явный цикл более выразителен. AG>>2. С ассоциативными контейнерами remove_if врядли даст ожидаемый результат B>С ассоциативными контейнерами remove_if просто не будет компилиься.
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, A.Grom, Вы писали:
AG>>Конечно, код так выглядит более читаемо, но есть 2 неприятности, большая и маленькая
AG>>1. Не всегда удобно условие засовывать в предикат B>Тут могут помочь библиотеки типа boost::bind и boost::lambda, но, само собой, иногда явный цикл более выразителен. AG>>2. С ассоциативными контейнерами remove_if врядли даст ожидаемый результат B>С ассоциативными контейнерами remove_if просто не будет компилиься.
Если контейнер — std::set, то во всяком случае в VC 7.1 прекрасно компилируется, как ни странно. Говорят, что это момент в пресловутом стандарте, можно толковать двояко.
Здравствуйте, Warturtle, Вы писали:
W>Если контейнер — std::set, то во всяком случае в VC 7.1 прекрасно компилируется, как ни странно. Говорят, что это момент в пресловутом стандарте, можно толковать двояко.
Здравствуйте, A.Grom, Вы писали:
AG>Зачем так сложно? AG>erase возвращает ближайший валидный итератор, следующий за удалённым значением, или .end() если в контейнере больше ничего нет.
AG>
AG> table_iter_t it = table.begin();
AG> while(it != table.end())
AG> {
AG> if (cond)
AG> it = table.erase(it);
AG> else
AG> ++it;
AG> }
AG>
Странно, у меня не убирает. Например
itPoint = points.begin();
while ( itPoint != points.end() )
{
CGPoint thisPoint = (*itPoint); // все время те же значения!
itPoint = points.erase(itPoint);
}
Похоже erase() не сдвигается сам к след валидному итератору. Хотя размер уменьшается
Здравствуйте, Bell, Вы писали:
B>Однако в случае, когда итератор вектора — обычный указатель, то этот код будет работать, причем правильно. Но если поменяется реализация STL, и в этой реализации вектор будет иметь "полноценные" итераторы, то сюрпризы обеспечены.
Ну дык всего то делов работать remov'ом с указателями а не итераторами, потом только resize сделать.
Re[2]: вопрос про stl, vector::erase
От:
Аноним
Дата:
07.06.05 07:17
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:
КД>Еще можно удалять элементы начиная с хвоста
Сложность квадратичная. Если удалять все нечётные например...
Re: вопрос про stl, vector::erase
От:
Аноним
Дата:
07.06.05 14:42
Оценка:
Здравствуйте, BlackBox, Вы писали:
BB>Добрый день.
BB>Мне надо в цикле перебирать значения хранящиеся в векторе. При определенном условии я должен удалить текущее знаечение из вектора и продолжить обход.
BB>Сейчас сделал так:
BB>
BB>...
BB>table_iter_t it = table.begin();
BB>for (int i=0; it != table.end(); it++, i++)
BB>{
BB>...
BB> if (cond)
BB> {
BB> table.erase(it);
BB> i--;
BB> it = table.begin()+i;
BB> continue;
BB> }
BB>...
BB>}
BB>
BB>Легальный ли это код или лучше сделать c remove+erase?
BB>Заранее спасибо за ответы.
Вариант c remove_if — erase выглядит примерно так. cond — у тебя предикат