Что происходит с итератором STL после стирания его в VS, UNIX/Linux?

Благодаря Ивану Стоеву я начал изучать AutoMapper.Collection , который действительно является расширением, которое я надеялся найти. После реализации мои списки обновляются так, как я хотел. Конфигурация проста в моем использовании, так как мне нужно только указать Id моих объектов.

Моя начальная конфигурация изменена на:

using AutoMapper;
using AutoMapper.EquivalencyExpression;
[....]
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAutoMapper(cfg => {
                cfg.AddCollectionMappers();
                });
        }
[....]

И мой профиль отображения:

    CreateMap().ReverseMap()
        .ForMember(m => m.Id, opt => opt.Ignore());

    CreateMap().ReverseMap()
        .EqualityComparison((sir, si) => sir.Id == si.Id);

8
задан Kent Fredric 13 January 2009 в 00:52
поделиться

4 ответа

Да, при стирании итератора тот итератор получает так называемое сингулярное значение, что означает, что он больше не принадлежит никакому контейнеру. Вы не можете увеличить, постепенно уменьшить или считать его/запись в него больше. Корректный способ сделать тот цикл:

for(map<T, S*>::iterator it = T2pS.begin(); it != T2pS.end(); T2pS.erase(it++)) {
    // wilhelmtell in the comments is right: no need to check for NULL. 
    // delete of a NULL pointer is a no-op.
    if(it->second != NULL) {
        delete it->second;
        it->second = NULL;
    }
}

Для контейнеров, которые могли делать недействительным другие итераторы, когда Вы стираете один итератор, erase возвращает следующий допустимый итератор. Затем Вы делаете это с

it = T2pS.erase(it)

Это - то, как это работает на std::vector и std::deque, но не для std::map или std::set.

21
ответ дан 5 December 2019 в 06:39
поделиться

Я думаю, изменяете ли Вы набор, Вы делаете недействительным свой итератор. Вы не можете полагаться на поведение, как Вы узнали.

0
ответ дан 5 December 2019 в 06:39
поделиться

Посмотрите это:

for (i = v.begin(); i != v.end(); ) {
  //...
  if (erase_required) {
      i = v.erase(i);
  } else {
      ++i;
  }
}
0
ответ дан 5 December 2019 в 06:39
поделиться

После вызова erase на итераторе в a std::map, это делается недействительным. Это означает, что Вы не можете использовать его. Попытка использовать его (например, путем постепенного увеличения его) недопустима и может заставить что-либо происходить (включая катастрофический отказ). Для a std::map, вызов erase на итераторе не делает недействительным никакой другой итератор так (например), после этого вызова, (пока it не был T2pS.end()), это будет допустимо:

T2pS.erase( it++ );

Конечно, при использовании этого подхода Вы не захотите безусловно увеличивать it в для цикла.

Для этого примера, тем не менее, почему беспокойство для стирания в для цикла? Почему не только называют T2pS.clear () в конце цикла.

С другой стороны, похоже, что у Вас есть необработанный указатель 'справа' карты, но карта, кажется, владеет резким для возражения. В этом случае, почему бы не сделать вещь справа от карты своего рода интеллектуальным указателем, таким как станд.:: tr1:: shared_ptr?

[Кстати, я не вижу шаблонных параметров к map. У Вас есть typedef'ed определенное инстанцирование std::map как map в локальном пространстве имен?]

4
ответ дан 5 December 2019 в 06:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: