ошибка с вектором::reverse_iterator в режиме отладки, но не в выпуске

#c #vector #stl #reverse-iterator

Вопрос:

Я использую reverse_iterator для поиска своего вектора и использую pop_back для стирания элементов.Но это вызывает некоторую ошибку в режиме отладки. Мой код таков:

 #include <iostream>
#include <vector>
#include <string>
using namespace std;

struct Student{
    string name;
    int score;
};

int main()
{
    vector<Student> testVec;
    testVec.push_back(Student{ "Lilei",50 });
    testVec.push_back(Student{ "YangFeifei",80 });
    testVec.push_back(Student{ "WuMing",80 });
    for (auto it = testVec.rbegin(); it != testVec.rend();   it){
        if (it == testVec.rbegin()) continue;
        while (it != testVec.rbegin()) {
            std::cout << amp;(*testVec.rbegin()) << ", ";
            std::cout << amp;(*it) << std::endl;

            testVec.pop_back();

            std::cout << amp;(*testVec.rbegin()) << ", ";
            std::cout << amp;(*it) << std::endl; // where error occur!
        }
    }
    std::cout << "Hello World!n";
}
 

Комментарии:

1. Существует большая вероятность того, что, если отладочная сборка что-то поймает, что-то не так. В сборке выпуска, похоже, все работает, но во многих случаях вы будете менять память там, где не хотите, и вы узнаете об этом только позже. К тому времени это будет сложнее отладить… так что отнеситесь к своему предупреждению об отладке сборки серьезно!

2. Пожалуйста, укажите ошибки в вопросе, когда вы их получите.

Ответ №1:

В этой документации std::vector<>::pop_back() говорится, что:

Итераторы и ссылки на последний элемент, а также итератор end() становятся недействительными.

Следовательно, ваш it итератор недействителен после вашего вызова pop_back() . Поведение разыменования этого итератора не определено, поэтому поведение вашей программы будет непредсказуемым.

В вашем конкретном случае возможно, что в отладочных сборках существуют некоторые дополнительные методы для среды выполнения, позволяющие определить, что вы допустили ошибку, но эти проверки могут быть дорогостоящими для производительности, поэтому могут не включаться в сборку выпуска. В любом случае, такое поведение не гарантируется. Решение состоит в том, чтобы не использовать it его после вызова pop_back() .

Комментарии:

1. Я думал, что мой it итератор не дошел до последнего элемента перед вызовом pop_back() . И я проверил несколько разных случаев. Случай, it когда итератор указывает на второй элемент снизу, pop_back() и случай, когда итератор указывает на третий элемент снизу. И результат показывает, что в первом случае возникает ошибка, но не во втором случае. Таким образом, оба итератора указывают на последний элемент до и после вызова pop_back() , будут недействительными. Верно?