Удаление элемента std::vector C++

213
05 октября 2018, 08:10

Есть следующий код:

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)

Элемент, который я хочу удалить точно присутствует в векторе в момент удаления.

Answer 1

Естественно программа крашится, так как вы пытаетесь удалить элемент, которого не существует, так как в данном случае у вас вектор состоит только из одного элемента. Если вы хотите удалить этот единственный элемент, то нужно убрать 1 из вашего же примера:

vector.erase(vector.begin());

В этом случае программа не будет крашится, а элемент удалится.

PS по поводу того, что элемент все равно отображается - в этом ничего удивительного, так как удаление элемента - это не его затирание!!! Вам следует поближе познакомится с памятью и понять как происходит занесение данных в память и их удаление. В кратце скажу: при "удалении" элемента ячейки памяти в которой находится элемент просто помечаются как вакантные. Они все еще существуют, но вот сохранение данных в них не гарантировано. В случае вектора - тоже самое. Ваша удаленная ячейка все еще будет содержать тот же указатель пока не будет перезаписана при следующем добавлении элемента.

Answer 2

vector.erase(vector.begin() + 1); Приводит к неопределенному поведению, так как итератор vector.begin() + 1 не указывает на элемент вектора.

Даже если правильно удалить первый элемент вектора, попытка обращения к нему vector[0]; тоже приводит к неопределенному поведению, так как указанное смещение элемента находится за границами (теперь уже пустого) вектора.

Answer 3

Соглавно тем пояснениям, что вы дали к комментариях, Ваша функция getLoot() при каждом вызове создает и возвращает новую копию вектора. Это сразу означает, что

currentRoom->getLoot().erase(currentRoom->getLoot().begin() + i); 

приводит у неопределенному поведению, которое вы и наблюдаете. Вызов метода erase() делается для одной копии вектора, а вычисление итератора - для совсем другой. В метод erase() вы передается итератор от совершенно постороннего вектора.

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

READ ALSO
Как добавить элемент в вектор по указателю?

Как добавить элемент в вектор по указателю?

Программа крашится в рантайме при попытке исполнить

152
Ошибка SIGSEGV (Segmentation fault)

Ошибка SIGSEGV (Segmentation fault)

Есть функция:

189
Как определить Activity?

Как определить Activity?

Есть два ActivityВ обоих RecyclerView с CardView

179
Парсинг различных форматов Date

Парсинг различных форматов Date

Долго пытался разобраться как парсить различные форматы датНа входе такие строки:

146