在C ++中释放指针的std :: vector的正确方法是什么?

时间:2010-07-27 15:04:56

标签: c++ memory vector containers delete-operator

我搜索了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;
}

这是否会使每次删除时的向量无效?我很困惑。

10 个答案:

答案 0 :(得分:17)

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

但是如果你真的需要一个指针向量,那么你做它的方式就好了(但.clear()向量后缀,如果它不会被立即销毁,那么它就不是满是悬垂的指针)

声明

delete *it;

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

答案 1 :(得分:7)

Boost ptr_vector救援!

完全符合您的要求,无需迭代和删除std :: vector

的内容

答案 2 :(得分:4)

另一种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();

答案 3 :(得分:2)

通常在C ++中,您应该尽可能地隐藏内存管理以避免内存错误。除非你正在进行大量的指针复制并且非常关心性能,否则我只会使用shared_ptr。

它是TR1标准的一部分,可以在大多数现代C ++编译器中使用(http://anteru.net/2008/09/01/260/),非常适合火灾和忘记内存管理。

答案 4 :(得分:1)

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

如果你删除了这个向量,而其他人仍然坚持使用其中一个指针,那么如果他们试图取消引用它,你将会得到一些非常讨厌的行为。共享指针可以让你头疼。

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

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

但要回答你的追求,不,那没关系。您没有更改it,而是要更改*it

答案 7 :(得分:0)

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

有关开发人员还希望在循环后删除所有i以及解决方案(vector_day.clear())的情况,请参阅this question

答案 8 :(得分: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;
         }
      };
};

答案 9 :(得分:0)

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

while (!vector_day.empty()) {
    Day* day = vector_day.back();
    vector_day.pop_back();
    delete day;
}