Есть следующий код:
std::vector<Room*> vector;
Room* room = model->getCurrent();
vector.push_back(room);
std::cout<< "before: "<<vector[0];
vector.erase(vector.begin() + 1);
std::cout<< "after: "<<vector[0];
В случае, когда я пытаюсь удалить элемент, на который указывает итератор начала вектора, ничего не происходит и элемент выводится в обоих случаях и имеет один адрес. Если же я пытаюсь удалить элемент, указанный в коде, то программа крашится в рантайме:
Process finished with exit code -1073740940 (0xC0000374)
Видимо, я чего то не понимаю в работе с элементами по указателю. Подскажите, пожалуйста, как в итоге мне удалить элемент?
Конкретизирую свой вопрос, я спросил немного не о том. Скажите, пожалуйста, что конкретно не так здесь:
for (int i = 0; i < currentRoom->getLoot().size(); ++i) {
if (currentRoom->getLoot()[i]->getName() == item)
if (currentRoom->getLoot()[i]->getPickable()) {
inventory.push_back(currentRoom->getLoot()[i]);
currentRoom->getLoot().erase(currentRoom->getLoot().begin() + i);
return 0;}
На строке с erase приложение завершается с ошибкой
Process finished with exit code -1073740940 (0xC0000374)
Элемент, который я хочу удалить точно присутствует в векторе в момент удаления.
Естественно программа крашится, так как вы пытаетесь удалить элемент, которого не существует, так как в данном случае у вас вектор состоит только из одного элемента. Если вы хотите удалить этот единственный элемент, то нужно убрать 1 из вашего же примера:
vector.erase(vector.begin());
В этом случае программа не будет крашится, а элемент удалится.
PS по поводу того, что элемент все равно отображается - в этом ничего удивительного, так как удаление элемента - это не его затирание!!! Вам следует поближе познакомится с памятью и понять как происходит занесение данных в память и их удаление. В кратце скажу: при "удалении" элемента ячейки памяти в которой находится элемент просто помечаются как вакантные. Они все еще существуют, но вот сохранение данных в них не гарантировано. В случае вектора - тоже самое. Ваша удаленная ячейка все еще будет содержать тот же указатель пока не будет перезаписана при следующем добавлении элемента.
vector.erase(vector.begin() + 1);
Приводит к неопределенному поведению, так как итератор vector.begin() + 1
не указывает на элемент вектора.
Даже если правильно удалить первый элемент вектора, попытка обращения к нему vector[0];
тоже приводит к неопределенному поведению, так как указанное смещение элемента находится за границами (теперь уже пустого) вектора.
Соглавно тем пояснениям, что вы дали к комментариях, Ваша функция getLoot()
при каждом вызове создает и возвращает новую копию вектора. Это сразу означает, что
currentRoom->getLoot().erase(currentRoom->getLoot().begin() + i);
приводит у неопределенному поведению, которое вы и наблюдаете. Вызов метода erase()
делается для одной копии вектора, а вычисление итератора - для совсем другой. В метод erase()
вы передается итератор от совершенно постороннего вектора.
В любом случае, пытаться удалять что-то во временной копии вектора - бессмысленная затея, ибо никакого влияния на оригинальный вектор это действие не окажет.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Долго пытался разобраться как парсить различные форматы датНа входе такие строки: