Почему итераторы 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();
}