17

我搜索了 StackOverflow,但找不到这个问题的答案。

假设我有一个std::vector<Day *> vector_day- 即 - 一个指向Day对象的指针向量。现在我push_backvector_day很多元素:

vector_day.push_back(new Day(12));
vector_day.push_back(new Day(99));
vector_day.push_back(new Day(71));
...

现在在某些时候我不再需要vector_day. 释放内存的正确方法是什么?

这是正确的方法:

for (std::vector<Day *>::iterator i = vector_day.begin(); i != vector_day.end(); ++i) {
    delete *i;
}

这不会在每次删除时使向量无效吗?我很困扰。

4

10 回答 10

18

如果您不是绝对需要,最好的方法是不要首先将指针放入向量中。

但是如果你确实需要一个指针向量,那么你这样做的方式就很好(但是.clear()向量后缀,如果它不会立即被销毁,那么它就不会充满悬空指针)

该声明

delete *it;

对迭代器没有影响。它不会更改迭代器、使迭代器无效或从集合中删除迭代器引用的指针。它所做的只是释放迭代器指向的指针所指向的内存。指针本身必须从集合中单独删除。

于 2010-07-27T15:07:46.510 回答
7

提升 ptr_vector进行救援!

完全满足您的需要,无需迭代和删除 std::vector 的内容

于 2010-07-27T18:40:08.740 回答
5

另一种 C++ 方法是定义一个辅助结构:

struct delete_ptr { // Helper function to ease cleanup of container
    template <typename P>
    void operator () (P p) {
        delete p;
    }
};

然后使用算法:

std::for_each(vector_day.begin(), vector_day.end(), delete_ptr());
vector_day.clear();
于 2010-07-27T15:59:51.947 回答
2

一般来说,在 C++ 中,您应该尽可能隐藏内存管理以避免内存错误。除非您要大量复制指针并且非常关心性能,否则我只会使用 shared_ptr。

它是 TR1 标准的一部分,可在大多数开箱即用的现代 C++ 编译器 ( http://anteru.net/2008/09/01/260/ ) 中使用,并且非常适合用于内存管理。

于 2010-07-27T16:12:35.933 回答
1

您可能应该使用某种托管指针,很可能是共享指针。

如果您在其他人仍然持有其中一个指针的情况下删除该向量,那么如果他们试图取消引用它,您将得到一些非常讨厌的行为。共享指针将为您省去头疼的问题。

如果您可以保证在删除向量后没有其他内容会引用指针,那么您仍然可以从使用自动指针中受益。当向量被销毁时,它将为您管理释放。开销很小,它使您的生活更轻松。

于 2010-07-27T15:18:04.093 回答
0

没关系。您正在删除*i(向量元素指向的对象)而不是i(向量元素),因此向量不会失效。

有关开发人员还想删除所有 s 的情况以及循环后的解决方案 ( ),请参阅此问题。ivector_day.clear()

于 2010-07-27T15:50:43.250 回答
0

首先,您从 切换iit,但我认为这只是一个错字。

但是回答你的问题,不,没关系。你没有变it,你在变*it

于 2010-07-27T15:09:00.493 回答
0

这是我不久前在处理相同问题时写的一个方便的类。我正在将一些代码从旧的基于 RogueWave 的向量和列表转换为基于 STL 的向量和列表,并且需要一些方法来模拟 RW 的指针列表的 clearAndDestroy() 方法。可以重写 clearAndDestroy() 方法以处理不同的结构类型(为简洁起见,我在这里只包含了向量)。

class StlUtils
{
   public:

      /**
       * This method provides a templated way to destroy a std::vector
       * full of pointers.  It is basically a replacement for the RW
       * vector class' clearAndDestroy methods.  The list argument is
       * returned empty.
       *
       * @param list the list of pointers to be destroyed.
       */
      template<class T> static void clearAndDestroy(
         std::vector<T*> &itemList)
      {
         for_each(itemList.begin(), itemList.end(),
                  stl_deleter<T>());
         itemList.clear();
      }

   private:

      /**
       * Templated member function for use with the clearAndDestroy()
       * method.  It provides the method needed by for_each to do the
       * actual deletion.
       */
      template<class T> struct stl_deleter
      {
         void operator() (T* x) {
            if (x != NULL)
               delete x;
         }
      };
};
于 2010-07-27T21:42:59.697 回答
0

从数组中添加或删除元素的操作可能会使迭代器无效,请查看文档以了解不同容器类型的特定规则。使用delete,您将作用于数组元素中包含的数据,而不是作用于数组的形状。迭代器遍历容器的形状,它们不关心它的内容。

于 2010-07-27T15:07:53.593 回答
0

另一种迭代+删除的方法是使用while(!empty)循环。这种技术的优点是元素首先从容器中删除,然后删除。这对任何容器都是安全的:

while (!vector_day.empty()) {
    Day* day = vector_day.back();
    vector_day.pop_back();
    delete day;
}
于 2018-07-02T06:51:21.013 回答