Всякий раз, когда вы изменяете диапазон, вы должны убедиться, что вы обновляете итератор, который используется для перемещения диапазона, таким образом, который совместим с тем, как итераторы недействительны при удалении из диапазона.
Простым примером применения этого подхода к вектору является следующий цикл. Обратите внимание, что стирание отменяет все итераторы с момента стирания вперед, поэтому вам нужно получить свежий итератор при стирании, и вам также нужно каждый раз пересчитывать end()
(т. Е. Не вывести конечное вычисление из цикла):
for (auto it = m_activeConnections.begin(); it != m_activeConnections.end();)
{
if ((*it)->isClosed()) { it = m_activeConnections.erase(it); }
else { ++it; }
}
лучший способ удалить из вектора состоит в перемещение чтобы быть стертыми элементов к задней части вектора, а затем стирать весь спектр все сразу и избежать перемещения диапазона хвоста вокруг все времени. Как правило, мы делаем это с remove_if
, хотя вам нужно добавить немного хитрости также удалить pointees в вашем случае:
m_activeConnections.erase(
std::remove_if(m_activeConnections.begin(),
m_activeConnections.end(),
[](Connection * p) {
if (p->isClosed()) { delete p; return true; }
return false;}),
m_activeConnections.end());
Вы можете избежать этого обмана, если вы изменили свой контейнер std::vector<std::unique_ptr<Connection>>
: Есть один класс за ответственность (вектор содержит, единственный указатель удаляет), и алгоритмы становятся составными.
Если вы не можете сделать ваш код простым путем выбора соответствующих абстракций, вы также можете попробовать более сложный алгоритм: Partition диапазон первого в соответствии с необходимостью удаления, а затем удалить, а затем удалить диапазон:
auto it = std::stable_partition(m_activeConnections.begin(),
m_activeConnections.end(),
[](Connection * p) { return p->isClosed(); });
for (auto kt = it; kt != m_activeConnections.end(); ++kt)
{
delete *kt;
}
m_activeConnections.erase(it, m_activeConnections.end());
О, спасибо, я новичок в C++. Я привык к java и не обращал на это внимания. Спасибо. – jack
На самом деле, 'remove_if' не будет работать здесь, если целью является как« удалить »элемент, так и удалить элемент. Если алгоритмный подход должен быть использован, сначала 'std :: stable_parttion', а затем' delete' и стирание элементов на «плохой» стороне раздела. – PaulMcKenzie
@PaulMcKenzie: Хорошо, я обновил ответ! –