【问题标题】:C++ vector dynamic memory deallocation/deleteC++向量动态内存释放/删除
【发布时间】:2014-02-21 17:47:05
【问题描述】:

当我尝试删除对象的动态向量的动态内存元素时,我必须多次迭代向量的整个大小以确保完全解除分配。

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

当我尝试删除时,向量似乎每隔一个元素就迭代一次,因为我需要额外的 while 循环来确保完全释放。

我似乎遗漏了有关向量内部工作的一些信息,我尝试阅读向量 c++ 参考,并且我了解向量将元素存储在一个连续的位置,并且它们为可能的增长分配了额外的存储空间,但我未能理解这段代码的行为。

【问题讨论】:

  • cars = new vector&lt;CV*&gt;; 这是个坏主意,为什么不直接vector&lt;CV*&gt; cars;?你持有原始指针项目已经使一切变得足够复杂......
  • 你注意到有std::erase()函数顺便说一句。
  • @πάνταῥεῖ 没有std::erase 功能。你的意思是std::vector::erase 还是std::remove
  • @FrançoisMoisan 当然是后者,谢谢!
  • 与其从向量中一次删除一个元素(强制重新定位所有后续元素),为什么不只是delete所有元素然后在向量上调用clear()

标签: c++ memory dynamic vector


【解决方案1】:

您可以编写一个通用函数来处理向量元素的释放和擦除

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

一些意见

  • 请始终与empty 核对空容器
  • vector&lt;T*&gt;* 存储在智能指针中以避免内存泄漏

【讨论】:

    【解决方案2】:

    当你从向量中删除一个元素时,之后的元素会移动一个位置。当你擦除索引 0 中的元素时,索引 1 中的元素将被移动到索引 0,并且不会在下一次迭代中被擦除。

    从循环中删除。无论如何,向量析构函数中的元素都会被擦除。

    【讨论】:

    • 好的,我知道当特定元素被擦除或移除时,元素必须移动。我想我可以释放所有元素,然后只调用一次 vector::clear 以使向量大小为 0 并为空。
    • @WadeG 你可以使用 clear 来清空向量,但是如果你在这之后立即删除向量是多余的。
    【解决方案3】:

    我认为这里真正的问题是您错过了 for 循环条件检查。 我对你的代码做了一个小改动:

    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. 使用栈上的vector对象会更好。

    【讨论】:

      【解决方案4】:

      发生这种情况的原因很简单,你通过擦除元素 i 然后增加 i...

      i = 0:汽车 = {0}[1][2][3]

      擦除(开始 + i)

      i = 0:汽车 = {1}[2][3]

      我++

      i = 1:汽车 = [1]{2}[3]

      擦除(开始 + i)

      i = 1:汽车 = [1]{3}

      我++

      i >= 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();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-22
        • 1970-01-01
        • 2015-10-15
        相关资源
        最近更新 更多