Проблема удаления отдельного элемента вектора в 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 должен быть передан явно, иначе он действительно не будет работать.

Другие вопросы по тегам