Проблема удаления отдельного элемента вектора в C++
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test (){ cout<<"Const\n"; }
~Test (){ cout<<"Dest\n"; }
};
int main( )
{
vector<Test *> tVec;
tVec.push_back(new Test());
tVec.push_back(new Test());
tVec.insert(tVec.end(),new Test());
tVec.emplace(tVec.end(),new Test[4]);
vector<Test *>::iterator it;
for(it = tVec.begin(); it != tVec.end(); it++)
{
delete *it;
it = tVec.erase(it);
}
return 0;
}
ВЫХОД:
Конст Конст Конст Конст Конст Конст Дест Дест
Только два деструктора были вызваны, в то время как 8 конструктор был вызван. Я знаю последние четыре объекта, которые я создал как массив. Есть ли общий способ удаления отдельных объектов внутри вектора. Второй Как получить доступ к этим отдельным элементам массива.
2 ответа
(Формально поведение вашей программы не определено: вы никогда не должны смешивать new[]
с delete
каждый new
должен быть сбалансирован с delete
и каждый new[]
сбалансирован с delete[]
.)
Взаимодействие it = tVec.erase(it);
с it++
в for
петля дает вам гипс. (Итератор возвращается erase
уже следующий).
Вы упускаете все остальные элементы вектора.
Удалить оператор приращения из for
петля (мой любимый выбор) и все будет хорошо.
Что касается общего способа, если вы должны были использовать std::vector<std::unique_ptr<Test>>
вместо этого, тогда значительно проще и надежнее tVec.clear()
сделал бы работу. Или использовать std::vector<Test>
и использовать (i) emplacement и (ii) доверие к вашему компилятору, чтобы избежать любых копий значений.
Вот версия, которая действительно будет вызывать все деструкторы, включая массивы:
void ArrayDeleter(Test *t) {
delete[] t;
};
int main()
{
vector<shared_ptr<Test> > tVec;
tVec.push_back(make_shared<Test>());
tVec.push_back(make_shared<Test>());
tVec.insert(tVec.end(), make_shared<Test>());
tVec.emplace(tVec.end(), shared_ptr<Test>(new Test[4], ArrayDeleter));
tVec.clear();
return 0;
}
Тем не менее, ArrayDeleter должен быть передан явно, иначе он действительно не будет работать.