简体   繁体   English

C ++向量动态内存释放/删除

[英]C++ vector dynamic memory deallocation/delete

When I try and delete dynamic memory elements of a dynamic vector of objects, I have to iterate over the entire size of the vector more than once to ensure complete deallocation. 当我尝试删除动态对象向量的动态内存元素时,我必须多次遍历向量的整个大小以确保完全释放。

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;

}

This will output: 这将输出:

  size:2
  size:1
  size:0

The vector seems to iterate over every second element when I try to delete, as I require the extra while loop to ensure total deallocation. 当我尝试删除时,向量似乎迭代每个第二个元素,因为我需要额外的while循环来确保完全释放。

I seem to be missing something about the internal workings of vector, I've tried reading the vector c++ reference and I understand that vectors store elements in a contiguous location and that they allocate extra storage for possible growth, but I fail to understand the behaviour of this code. 我似乎错过了关于向量的内部工作的一些东西,我已经尝试阅读向量c ++参考,我理解向量将元素存储在一个连续的位置,并且他们为可能的增长分配额外的存储空间,但我无法理解这种行为这段代码。

You can write a generic function to handle both deallocation and erasure of the vector's elements 您可以编写一个泛型函数来处理向量元素的释放和擦除

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

Some remarks 一些评论

  • Always check with empty for empty container 务必检查empty的空容器
  • Store your vector<T*>* in a smart pointer to avoid memory leaks vector<T*>*在智能指针中以避免内存泄漏

When you erase an element from vector, elements after that are moved by one place. 从向量中删除元素时,之后的元素将移动一个位置。 When you erase the element in index 0, the element in index 1 will be moved to index 0 and will not be erased in the next iteration. 擦除索引0中的元素时,索引1中的元素将移动到索引0,并且在下一次迭代中不会被擦除。

Take the erase from the loop. 从循环中删除。 Elements will be erased in the vectors destructor anyway. 无论如何,元素将在向量析构函数中被擦除。

I think the real problem here is you miss the for loop condition check. 我认为这里真正的问题是你错过了for循环条件检查。 I make a small change to your code: 我对您的代码做了一些小改动:

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

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

I have two suggestions which are also my questions: 我有两个建议也是我的问题:

  1. use smart pointer here to manage the resource can help you. 在这里使用智能指针来管理资源可以帮到你。

  2. use vector object on the stack will be better. 在堆栈上使用矢量对象会更好。

The reason this happens is very simple, you pull the rug out from under your own feet by erasing element i and then incrementing i... 发生这种情况的原因非常简单,你可以通过擦除元素i然后递增i来从自己的脚下拉出地毯......

i = 0: cars = {0}[1][2][3] i = 0:cars = {0} [1] [2] [3]

erase(begin + i) 擦除(开始+ i)

i = 0: cars = {1}[2][3] i = 0:cars = {1} [2] [3]

i++ 我++

i = 1: cars = [1]{2}[3] i = 1:cars = [1] {2} [3]

erase(begin + i) 擦除(开始+ i)

i = 1: cars = [1]{3} i = 1:cars = [1] {3}

i++ 我++

i >= cars.size() i> = cars.size()

Using erase like this is inefficient. 像这样使用擦除是低效的。 You might consider the following two approaches: 您可以考虑以下两种方法:

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

or the far more efficient 或者效率更高

for (size_t i = 0; i < cars.size(); ++i) {
    delete cars[i];
}
cars.clear();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM