C ++删除矢量,对象,空闲内存

时间:2012-05-05 18:55:00

标签: c++ vector delete-operator

我对在C ++中删除东西感到困惑 如果我声明一个对象数组,并且我使用clear()函数。我可以确定内存已被释放吗?

例如:

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;

tempVector.pushback(obj1);
tempVector.pushback(obj2);

我可以安全地拨打清除以释放所有内存吗?或者我是否需要逐个删除才能逐个删除?

tempVector.clear();

如果将此场景更改为对象指针,答案是否与上述相同?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();

7 个答案:

答案 0 :(得分:77)

你可以调用clear,这会破坏所有对象,但这不会释放内存。循环使用各个元素也无济于事(你甚至建议对这些对象采取什么行动?)你可以做的是:

vector<tempObject>().swap(tempVector);

这将创建一个没有分配内存的空向量,并将其与tempVector交换,从而有效地释放内存。

C ++ 11也有函数shrink_to_fit,你可以在调用clear()之后调用它,理论上它会缩小容量以适应大小(现在为0)。但是,这是一个非约束性请求,您的实现可以忽略它。

答案 1 :(得分:21)

这里有两个不同的东西:

  1. 对象生命周期
  2. 存储时间
  3. 例如:

    {
        vector<MyObject> v;
        // do some stuff, push some objects onto v
        v.clear(); // 1
        // maybe do some more stuff
    } // 2
    

    1,您清除v:这会破坏它存储的所有对象。每个人都会得到它的析构函数,如果你写了一个,那么MyObject拥有的任何东西现在都被释放了。 但是,向量v有权保留原始存储空间以备日后使用。

    如果您决定在12之间推送更多内容,则可以节省时间,因为它可以重复使用旧内存。

    2,向量v超出范围:自1以来你推入它的任何对象都将被销毁(就好像你明确地再次调用了clear),但是现在底层存储也已发布(v将无法重新使用它。)


    如果我更改示例以使v成为指针,则需要显式删除它,因为超出2范围的指针不会为您执行此操作。在这种情况下,最好使用类似std::unique_ptr的内容,但如果不这样做,v被泄露,它分配的存储也将被泄露。如上所述,您需要确保删除v,并且调用clear是不够的。

答案 2 :(得分:14)

vector::clear()不释放向量分配的内存来存储对象;它为它所拥有的对象调用析构函数。

例如,如果向量使用数组作为后备存储并且当前包含10个元素,则调用clear()将调用数组中每个对象的析构函数,但后备数组将不会deallocated ,因此仍然有sizeof(T) * 10个字节分配给向量(至少)。 size()将为0,但size()返回向量中的元素数,不一定是后备存储的大小。

至于您的第二个问题,您使用new分配的任何内容都必须与delete取消分配。出于这个原因,通常不会维护指向向量的指针。很少(如果有的话)有充分的理由这样做,你可以防止矢量在离开范围时被清理干净。但是,无论分配方式如何,调用clear()仍将采取相同的行动。

答案 3 :(得分:2)

移动语义提供了一种直接释放内存的方法,只需简单地从空值中应用assignment (=) operator

std::vector<uint32_t> vec(100, 0);
std::cout << vec.capacity(); // 100

vec = vector<uint32_t>();    // Same as "vector<uint32_t>().swap(vec)";    
std::cout << vec.capacity(); // 0

它与其他答案中所述的基于“ swap()”的方法一样有效(实际上,两者在概念上都在做同一件事)。但是,在可读性方面,赋值版本可以更好地表达程序员的意图,同时更加简洁。

答案 4 :(得分:1)

  

如果我使用clear()成员函数。我可以确定内存已释放吗?

否,clear()成员函数会破坏向量中包含的每个对象,但它会使向量的capacity保持不变。它会影响向量的大小,但不会影响容量。

如果要更改向量的容量,可以使用clear-and-minimize idiom,即创建一个(临时)空向量,然后交换两个向量。


您可以轻松了解每种方法如何影响容量。考虑下面的函数模板,该模板在传递的向量上调用clear()成员函数:

template<typename T>
auto clear(std::vector<T>& vec) {
   vec.clear();
   return vec.capacity();
}

现在,考虑将传递的矢量交换为空的函数模板empty_swap()

template<typename T>
auto empty_swap(std::vector<T>& vec) {
   std::vector<T>().swap(vec);
   return vec.capacity();
}

两个函数模板都在返回时返回向量的容量,然后:

std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';

输出:

1000
0

答案 5 :(得分:0)

如果你需要反复使用向量,并且当前代码在循环或每个函数调用中重复声明它,很可能会耗尽内存。我建议你在外面声明它,将它们作为指针传递给你的函数并使用:

my_arr.resize()

这样,您可以继续为向量使用相同的内存序列,而不是每次都请求新的序列。 希望这有帮助。 注意:将其调整为不同大小可能会添加随机值。如果需要,传递一个整数(如0)以初始化它们。

答案 6 :(得分:0)

您可以通过以下方式释放vector使用的内存:

  public subscribe = (data: IQueue) => {
    if (Queues.queues[data.name]) {
      const handler = Queues.queues[data.name].hasOwnProperty('handler');
    }
    Queues.queues[data.name] = data;
  };
  public unsubscribe = (queue, handler) => {
    const result = Queues.queues[queue];
  };