2016-04-17 2 views
1

Я заметил, что когда в этом коде выполняется оператор else if, destination, несмотря на то, что он не является разыменованным, представляется интерпретированным как фактическое значение, на которое он указывает вместо итератора. Это похоже на то, что он автоматически разыгрывается. Цикл for выполняется так, как вы ожидали, но идентификатор, например done, должен быть установлен на true, когда итераторы begin() и end() равны. destinations - это дека целых чисел, глобальных для этой функции.Итератор автоматически разыменовывается при указании на целое число

void removeDestination(int destinationFloor) 
{ 
    bool done = false; 
    while(!done && !destinations.empty()) 
    { 
     for (auto destination = destinations.begin(); destination != destinations.end(); ++destination) 
     { 
      if(*destination == destinationFloor) 
      { 
       destinations.erase(destination); 
       break; 
      } 
      else if(destination == destinations.end()) 
      { 
       done = true; 
      } 
     } 
    } 

} 

Спасибо за помощь.

+2

Какое поведение вашей программы заставило вас думать, что итератор был разыменован там? Это странный вывод. – user2357112

+0

@ user2357112, когда выполняется оператор 'else if', он сравнивает элемент, на который указывает' destination', с итератором 'end()', поэтому этот код создает бесконечный цикл. Я согласен, что это странно, но я заметил в отладчике, наблюдая изменения локальных значений в этой функции. – LBaelish

ответ

5

Проблема не имеет ничего общего с destination, будучи ложно разыменованным. else if ветвь никогда не принимается:

else if(destination == destinations.end()) 

destination, потому что если дойдет до конца destinations, то условие цикла:

for (auto destination = destinations.begin(); destination != destinations.end(); ++destination) 
//           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

останавливает цикл до else if может быть введен.

2

Я заметил, что когда инструкция else if выполняется в этом коде назначения, несмотря на то, что она не разыменована, представляется интерпретируемой как фактическое значение, на которое указывает вместо итератора.

Nope. if(*destination == destinationFloor) сравнивает значение указывает на итератор на значениеdestinationFloor. Принимая во внимание, что if(destination == destinations.end()) сравнивает два итератора.

адресаты являются деками целых чисел, глобальными для этой функции.

Глобальные переменные? Не использовать стандартные алгоритмы? Я бы посоветовал вам взглянуть на modern C++ book. В частности, код, который вы написали, является хорошо разрешенной проблемой. См. erase-remove idiom.

+0

Я ценю ссылку на erase-remove, эта функция действительно является частной функцией члена класса. Глобальная переменная, о которой я упоминал, является только частным членом данных. – LBaelish

3

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

Для dequeerasecan cause invalidation of all iterators, включая тот, который вы используете для цикла.

Редактировать: как указано в комментариях, вы уже разработали стратегию для работы с недействительными итераторами. Это не очень эффективно, но это должно сработать. Ваша проблема заключается в неправильной настройке переменной done.

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

bool done = false; 
while(!done && !destinations.empty()) 
{ 
    done = true; 
    for (auto destination = destinations.begin(); destination != destinations.end(); ++destination) 
    { 
     if(*destination == destinationFloor) 
     { 
      destinations.erase(destination); 
      done = false; 
      break; 
     } 
    } 
} 
+0

Я понимаю недействительность проблемы итераторов. Это проблема, которую я пытался преодолеть, выйдя из итерации каждый раз, когда элемент удален, а затем перезапустив цикл for. – LBaelish

+0

@LBaelish жаль, что я пропустил эту маленькую деталь. Я обновлю ответ, когда подумаю об этом чуть больше. –