c ++ - исчезающая переменная - PullRequest
0 голосов
/ 06 июня 2018

Я пишу функцию для пересечения двух отсортированных vector<size_t> с именами a и b.Функция выполняет итерацию по обоим векторам, удаляя из a все, что не находится в b, поэтому все, что остается в a, является пересечением двух.Код здесь:

void intersect(vector<size_t> &a, vector<size_t> &b) {
  vector<size_t>::iterator aItr = a.begin();
  vector<size_t>::iterator bItr = b.begin();
  vector<size_t>::iterator aEnd = a.end();
  vector<size_t>::iterator bEnd = b.end();

  while(aItr != aEnd) {
    while(*bItr < *aItr) {
      bItr++;
      if(bItr == bEnd) {
        a.erase(aItr, aEnd);
        return;
      }
    }
    if (*aItr == *bItr) aItr++;
    else aItr = a.erase(aItr, aItr+1);
  }
}

Я получаю очень ошибку.Я захожу в отладчик, и как только он проходит строку 8 "while(*bItr < *aItr)" b, кажется, исчезает.Отладчик, кажется, не знает, что b даже существует!Когда b возвращается после того, как возвращается к вершине цикла, он принимает значения a!

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

Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Вы предполагаете, что b содержит хотя бы один элемент.Чтобы решить эту проблему, вы можете добавить это до первого цикла:

if (bItr == bEnd)
{
    a.clear();
    return;
}

Кроме того, поскольку вы удаляете элементы из a, aEnd станет недействительным.Замените каждое использование aEnd на a.end().


std::set_intersection может сделать все это для вас:

void intersect(vector<size_t> &a, const vector<size_t> &b)
{
    auto it = set_intersection(a.begin(), a.end(), b.begin(), b.end(), a.begin());
    a.erase(it, a.end());
}
0 голосов
/ 06 июня 2018

Что ж, возможно, вам следует сначала решить главную проблему с вашим кодом: аннулирование итератора.

См .: Правила аннулирования итератора здесь, в StackOverflow.

Когда вы стираетеэлемент в векторе, итераторы в этот вектор в точке удаления и далее не гарантируются действительными.Ваш код, тем не менее, предполагает такую ​​валидность для aEnd (спасибо @SidS).

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

Плюс, как @KT.примечания: ваши стирания могут быть очень дорогими, что делает ваш алгоритм потенциально квадратичным по времени на длину a.

...