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

发布于 2024-09-12 03:58:35 字数 572 浏览 8 评论 0原文

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

假设我有一个 std::vector; vector_day - 即指向 Day 对象的指针向量。现在我将许多元素push_back添加到vector_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;
}

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

I searched StackOverflow but couldn't find the answer to this question.

Suppose I have a std::vector<Day *> vector_day - that is - a vector of pointers to Day object. Now I push_back to vector_day many elements:

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

Now at some point I no longer need vector_day. What is the right way to free the memory?

It this the correct way:

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

Doesn't this invalidate the vector on each deletion? I am very confused.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

月竹挽风 2024-09-19 03:58:35

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

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

该语句

delete *it;

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

The best way is not to put pointers into the vector in the first place if you don't absolutely need to.

But if you do really need to have a vector of pointers, then the way you are doing it is just fine (but .clear() the vector afterwords, if it won't be immediately destroyed, so that it's not full of dangling pointers)

The statement

delete *it;

has no effect on the iterator. It does not change the iterator, invalidate the iterator, or remove the pointer referred to by the iterator from the collection. All it does is free the memory that the pointer referred to by the iterator points at. The pointer itself must be removed from the collection separately.

不顾 2024-09-19 03:58:35

Boost ptr_vector 来救援!

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

Boost ptr_vector to the rescue!

Does exactly what you need, without the need to iterate and delete the contents of the std::vector

自由范儿 2024-09-19 03:58:35

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

Another C++ way to do this is to define a helper struct:

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

and then use the algorithms:

std::for_each(vector_day.begin(), vector_day.end(), delete_ptr());
vector_day.clear();
同尘 2024-09-19 03:58:35

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

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

In general in C++ you should hide memory management as much as possible to avoid memory errors. Unless you're doing a lot of copying of the pointers and care a lot about performance I would just use a shared_ptr.

It's part of the TR1 standard and is available in most modern C++ compilers out of the box (http://anteru.net/2008/09/01/260/) and is great for fire and forget memory management.

毁虫ゝ 2024-09-19 03:58:35

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

如果您删除该向量,而其他人仍然持有这些指针之一,那么如果他们尝试取消引用它,您将得到一些非常令人讨厌的行为。共享指针将为您省去这个麻烦。

如果您可以保证删除向量后没有其他任何东西会引用这些指针,那么您仍然可以从使用自动指针中受益。当向量被销毁时,它将为您管理重新分配。开销很小,而且使您的生活变得更加轻松。

You should probably be using some kind of managed pointer, most likely a shared pointer.

If you delete the vector while someone else is still holding on to one of those pointers, you're going to get some very nasty behaviour if they try to dereference it. A shared pointer will save you that headache.

If you can guarantee that nothing else will reference the pointers after the vector is deleted, then you can still benefit from using an auto pointer. It will manage deallocation for you when the vector is destroyed. The overhead is minimal, and it makes your life a lot easier.

甜是你 2024-09-19 03:58:35

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

Operations that add or remove elements from the array may invalidate the iterators, check the documentation for specific rules for the different container types. With delete, you're acting on the data contained in the array elements, not on the array's shape. Iterators traverse the container's shape, they don't care about its contents.

妄司 2024-09-19 03:58:35

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

但要回答你的问题,不,没关系。您不是在改变,而是在改变*it

First of all, you switched from i to it, but I assume that's just a typo.

But to answer your quest, no, that's fine. You are not changing it, you are changing *it.

鸠书 2024-09-19 03:58:35

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

请参阅此问题了解开发人员也希望删除所有i,并在循环后找到它的解决方案(vector_day.clear())。

It's just fine. You are deleting *i (object pointed by vector's element) and not i (vector's element), so the vector is not invalidated.

See this question for a case where the developer also wanted to delete all is, and for the solution for it (vector_day.clear()) after the loop.

2024-09-19 03:58:35

这是我不久前在处理同一问题时编写的一个方便的课程。我正在将一些代码从旧的基于 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;
         }
      };
};

Here's a handy class I wrote a while ago while dealing with the same issue. I was converting some code from old RogueWave-based vectors and lists to STL-based vectors and lists, and needed some way to emulate RW's clearAndDestroy() method for pointer lists. The clearAndDestroy() method can be overridden to handle different structure types (I only included vector here for brevity).

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;
         }
      };
};
眼泪都笑了 2024-09-19 03:58:35

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

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

Another way of iterating + deleting is by using while(!empty) loop.
The advantage of this technique is that an element is removed from container first, deleted afterwords. This is safe for any container:

while (!vector_day.empty()) {
    Day* day = vector_day.back();
    vector_day.pop_back();
    delete day;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文