2014-02-21 3 views
4

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

class CV{ 
    public: 
      float x; 
      float y; 

      CV(); 
      CV(float, float); 
      ~CV(); 
}; 


int main(){ 

    vector<CV*>* cars; 
    cars = new vector<CV*>; 


    //create objects with new, push into vetor 
    for(int j=0;j<4;j++){ 
      cars->push_back(new CV(10.0+j, 11.99+j)); 
    } 

    while(cars->size() > 0 ){ 
      for(int i=0;i<cars->size();i++){ 
        delete (*cars)[i]; 
        cars->erase(cars->begin()+i); 
      } 
      cout << "size:"<< cars->size() << endl; 
    } 

    delete cars; 
    return 0; 

} 

Этот выход будет:

size:2 
    size:1 
    size:0 

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

У меня, кажется, что-то не хватает о внутренних функциях вектора, я пробовал читать векторную ссылку C++, и я понимаю, что векторы хранят элементы в смежном местоположении и что они выделяют дополнительное хранилище для возможного роста, но я терпит неудачу чтобы понять поведение этого кода.

+3

'автомобили = новый вектор ;' Это плохая идея, почему бы не просто 'вектор автомобилей;'? То, что у вас есть необработанные указательные элементы, усложняет все, что уже достаточно ... –

+0

Вы заметили, что есть функция 'std :: erase()' BTW. –

+0

@ πάνταῥεῖ Нет функции 'std :: erase'. Вы имели в виду 'std :: vector :: erase' или' std :: remove'? –

ответ

1

Когда вы удаляете элемент из вектора, элементы после этого перемещаются одним местом. Когда вы стираете элемент в индексе 0, элемент в индексе 1 будет перемещен в индекс 0 и не будет удален на следующей итерации.

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

+1

Хорошо, я понимаю, что элементы должны сдвигаться, когда определенный элемент стирается или удаляется. Я думаю, что я могу освободить все элементы, а затем просто вызвать вектор :: clear один раз, чтобы сделать векторный размер 0 и пустым. –

+0

@WadeG Вы можете использовать clear для опорожнения вектора, но он лишний, если вы удалите вектор сразу после этого. – user2079303

2

Вы можете написать общую функцию, чтобы обрабатывать как открепление и стирание элементов вектора

template<typename T> 
void destroy_vector(std::vector<T*> &v) 
{ 
    while(!v.empty()) { 
     delete v.back(); 
     v.pop_back(); 
    } 
} 

Некоторые замечания

  • Всегда проверяйте с empty для пустого контейнера
  • Храните ваши vector<T*>* в умный указатель во избежание утечек памяти
0

Я думаю, что настоящая проблема здесь - пропустить проверку состояния цикла. я сделать небольшое изменение в код:

auto validateLoopCondition = [](int index, const vector<CV*> *vecpCV) 
{ 
    cout << "validate loop condition: i = " << index << ", size:" << vecpCV->size() 
     << (index < vecpCV->size() ? ", keep it" : ", break out\r\n---------------\r\n") 
     << endl; 
}; 

for (int i = 0; validateLoopCondition(i, cars) , i < cars->size(); i++) 
{ 
    delete (*cars)[i]; 
    cars->erase(cars->begin() + i); 
} 

cout << "size:" << cars->size() << endl; 


//-out put----------------------------------------------- 

validate loop condition: i = 0, size:4, keep it 
validate loop condition: i = 1, size:3, keep it 
validate loop condition: i = 2, size:2, break out 
--------------- 

size:2 
validate loop condition: i = 0, size:2, keep it 
validate loop condition: i = 1, size:1, break out 
--------------- 

size:1 
validate loop condition: i = 0, size:1, keep it 
validate loop condition: i = 1, size:0, break out 
--------------- 

size:0 

// ------------------------------- ----------------------

у меня есть два предложения, которые также являются мои вопросы:

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

  2. Использование векторного объекта в стеке будет лучше.

0

Причина, по которой это происходит очень просто, вы вытаскиваете ковер из-под ваших собственных ног, стирая элемент i, а затем увеличивая i ...

= 0: машины = {0} [1] [2] [3]

стирания (начало + I)

I = 0: автомобили = {1} [2] [3]

я ++

я = 1: машины = [1] {2} [3]

стирания (начало + I)

= 1: автомобили = [1] {3}

я ++

я> = cars.size()

Использование стирания, как это неэффективно. Вы могли бы рассмотреть следующие два подхода:

while (!cars.empty()) { 
    delete cars.back(); 
    cars.pop_back(); 
} 

или гораздо более эффективным

for (size_t i = 0; i < cars.size(); ++i) { 
    delete cars[i]; 
} 
cars.clear(); 
Смежные вопросы