我搜索了StackOverflow但找不到这个问题的答案。
假设我有一个std::vector<Day *> 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;
}
这是否会使每次删除时的向量无效?我很困惑。
答案 0 :(得分:17)
如果您不是绝对需要,最好的方法是不要将指针放在向量中。
但是如果你真的需要一个指针向量,那么你做它的方式就好了(但.clear()
向量后缀,如果它不会被立即销毁,那么它就不是满是悬垂的指针)
声明
delete *it;
对迭代器没有影响。它不会更改迭代器,使迭代器无效,也不会从集合中删除迭代器引用的指针。所有这一切都是释放迭代器引用的指针所指向的内存。指针本身必须单独从集合中删除。
答案 1 :(得分:7)
完全符合您的要求,无需迭代和删除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;
}