在 C++ 中释放 std::vector 指针的正确方法是什么?
我搜索了 StackOverflow 但找不到这个问题的答案。
假设我有一个 std::vector
- 即指向 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
如果不是绝对需要,最好的方法是不要首先将指针放入向量中。
但是如果你确实需要一个指针向量,那么你这样做的方式就很好(但是
.clear()
向量后缀,如果它不会立即被销毁,所以它没有充满悬空指针)该语句
对迭代器没有影响。它不会更改迭代器、使迭代器无效或从集合中删除迭代器引用的指针。它所做的只是释放迭代器引用的指针所指向的内存。指针本身必须单独从集合中删除。
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
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.
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
另一种 C++ 方法是定义一个辅助结构:
然后使用算法:
Another C++ way to do this is to define a helper struct:
and then use the algorithms:
一般来说,在 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.
您可能应该使用某种托管指针,很可能是共享指针。
如果您删除该向量,而其他人仍然持有这些指针之一,那么如果他们尝试取消引用它,您将得到一些非常令人讨厌的行为。共享指针将为您省去这个麻烦。
如果您可以保证删除向量后没有其他任何东西会引用这些指针,那么您仍然可以从使用自动指针中受益。当向量被销毁时,它将为您管理重新分配。开销很小,而且使您的生活变得更加轻松。
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.
从数组中添加或删除元素的操作可能会使迭代器无效,请检查文档以了解不同容器类型的特定规则。使用
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.首先,您从
i
切换到it
,但我认为这只是一个拼写错误。但要回答你的问题,不,没关系。您不是在改变
它
,而是在改变*it
。First of all, you switched from
i
toit
, 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
.没关系。您正在删除
*i
(向量元素指向的对象)而不是i
(向量元素),因此向量不会失效。请参阅此问题了解开发人员也希望删除所有
i
,并在循环后找到它的解决方案(vector_day.clear()
)。It's just fine. You are deleting
*i
(object pointed by vector's element) and noti
(vector's element), so the vector is not invalidated.See this question for a case where the developer also wanted to delete all
i
s, and for the solution for it (vector_day.clear()
) after the loop.这是我不久前在处理同一问题时编写的一个方便的课程。我正在将一些代码从旧的基于 RogueWave 的向量和列表转换为基于 STL 的向量和列表,并且需要某种方法来模拟 RW 的指针列表的 clearAndDestroy() 方法。可以重写clearAndDestroy()方法来处理不同的结构类型(为了简洁起见,我只在此处包含了向量)。
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).
迭代+删除的另一种方法是使用 while(!empty) 循环。
这种技术的优点是先从容器中删除元素,然后删除元素。这对于任何容器都是安全的:
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: