Лучший способ в Ситу удаления элемента

голоса
2

У меня есть набор объектов, которые я перебирать, однако я могу решить в ходе итерации, что один (или более) из этих объектов в настоящее время должны быть удалены.

Мой код выглядит следующим образом:

if( ! m_Container.empty() )
    {
        for(  typedefedcontainer::iterator it = m_Container.begin();
              it != m_Container.end(); 
              ++it  )
        {
            if( ! ( SomeFunction( (*it), test, TEST!, false ))  )
            {
            // If function returns false, delete object.
                m_Container.erase( it );
                AsyncResponseStore::iterator it = m_asyncResponses.begin();
            }

        }


    }

Но, конечно, когда я стираю объект Я получаю сообщение об ошибке: «Карта / набор итератор не incrementable». Может кто-то предложить лучший способ сделать это?

Смотрите: Что произойдет , если вы звоните УДАЛИТЬ () на элемент карты в то время как итерация от начала до конца?

Задан 09/12/2008 в 17:09
источник пользователем
На других языках...                            


3 ответов

голоса
6

Если контейнер поддерживает его (я подозреваю, что ваш не делает, но вопрос название носит общий характер, так что это может быть полезным для других, если не вы):

struct SomePredicate {
    bool operator()(typedefedcontainer::value_type thing) {
        return ! SomeFunction(thing, "test", "TEST", false);
    }
};

typedefedcontainer::iterator it;
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate());
m_Container.erase(it, m_Container.end());

m_Container должен иметь метод диапазона стирания, который включает в себя любую последовательность или ассоциативный контейнер. Он должен иметь изменяемый итератор, хотя, и я только заметил, что я изначально неправильно сообщение об ошибке: он говорит, что «карта / набор итератор не incrementable». Таким образом, я предполагаю, что ваш контейнер представляет собой карту или набор.

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

Кроме того, что SomePredicate может иметь конструктор с параметрами для хранения дополнительных параметров SomeFunction, так как в реальной жизни, я думаю, они непостоянные.

Вы могли бы на самом деле избавиться от SomePredicate полностью, если вы используете форсиро- привязку построить функтор. Ваш один лайнер будет затем по-настоящему массовым.

[Edit: Роб Уокер правильно отмечает в своем ответе предположение, что я делаю здесь, и что вопрос не состояние, которое является то, что все Стирание не может быть отложено до тех пор, после того, как итерация-и-тест проводится. Если SomeFunction доступ m_Container скрытым способом (например, глобальный, или потому, что SomeFunction фактически является функцией членом этого), и его результаты зависят от содержимого контейнера, то мой код не может быть эквивалентен коду спрашивающий в. Но я думаю, что мой код является «если не причина, чтобы не» по умолчанию.]

Ответил 09/12/2008 в 17:39
источник пользователем

голоса
6

Это зависит от контейнера. Контейнер списка поддерживает удаление во время перечисления, возвращая новый итератор от метода стирания, который представляет следующий элемент в списке. карта не поддерживает это.

Простой метод для отображения является аккумулировать элементы, которые вы хотите удалить, в отдельном списке, а затем перебрать этот список, когда вы закончили обработку карты, чтобы удалить элементы из карты. Это предполагает, что вы можете отложить удаление до итерации не завершена. Если нет, то у вас нет выбора, кроме как перезапуск итерации для каждого удаления.

Ответил 09/12/2008 в 17:18
источник пользователем

голоса
0

Зафиксировано следующее:

for(  typedefedcontainer::iterator it = m_Container.begin();
      it != m_Container.end(); 
        )
{
    if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
    {
    // If function returns false, delete object.
        m_Container.erase( it++ );
    }
    else
    { 
        ++i;
    } 

}

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

Ответил 09/12/2008 в 17:30
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more