Почему итераторы C++ вектора перед позицией стирания также становятся недействительными в visual studio?

int removeDuplicates(vector<int>& nums) {
    vector<int>::iterator iter = nums.begin();
    vector<int>::iterator test = nums.begin(); //used to test
    while (nums.begin() != nums.end())
    {       
        vector<int>::iterator temp = iter;
        vector<int>::iterator temp2 = ++iter;
        if (temp2 == nums.end()) break;
        if (*temp == *temp2)
        {           
            iter = nums.erase(temp);
            cout << *test << " ";  //test here, error happen

        }
    }
    return nums.size();
}
int main()
{
    vector<int> test = { 1,1,2,2,4,5,6,6 };

    int result = removeDuplicates(test);
}

сообщение об ошибке: "vector iterator not dereferencable!"

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

3 ответа

Это должно помочь вам.

int removeDuplicates(std::vector<int>& nums) 
{
    for (auto iter = nums.begin(); iter != nums.end(); /* DO NOT INCREMENT */)
    {
        if (std::find(iter + 1, nums.end(), *iter) != nums.end())
        {
            iter = nums.erase(iter);
        }
        else
        {
            ++iter;
        }
    }

    return static_cast<int>(nums.size());
}
 vector<int>::iterator iter = nums.begin();
 vector<int>::iterator test = nums.begin();

 vector<int>::iterator temp = iter;

temp, iter а также test указать на тот же элемент.

 iter = nums.erase(temp);

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

cout << *test << " ";

Недействительным test не выделен Поведение не определено.

Эта ситуация воспроизводится всякий раз, когда *temp == *temp2 верно в первой итерации. В последующих итерациях iter а также temp больше не указывают на первый элемент.

cppreference.com говорит следующее о vector::erase:

Делает недействительными итераторы и ссылки в или после точки удаления, включая итератор end().

Так что в вашем примере оба test а также temp инициализируются с nums.begin(), Когда вы стираете tempэто делает недействительным temp, Следовательно, вы должны убедиться, что temp будет повторно инициализирован или вы сохраните копию стертого элемента для последующего использования.

Так как насчет изменения вашего кода следующим образом:

int removeDuplicates(vector<int>& nums) {
    vector<int>::iterator iter = nums.begin();
    vector<int>::iterator test = nums.begin(); //used to test
    while (nums.begin() != nums.end())
    {
        vector<int>::iterator temp = iter;
        vector<int>::iterator temp2 = ++iter;
        size_t dist = std::distance(nums.begin(), temp);
        if (temp2 == nums.end()) break;
        if (*temp == *temp2)
        {
            iter = nums.erase(temp);
            test = nums.begin();
            test += dist;
            cout << *test << " ";  //test here, error happen

        }
    }
    return nums.size();
}
Другие вопросы по тегам