removing things from a pointer vector
我有一个这样的指针向量:
1 | vector<Item*> items; |
我想清除它。我试过了:
1 2 3 | for (unsigned int i = 0; i < items.size(); i++) delete items.at(i); items.clear(); |
,
1 2 3 4 5 | while (!items.empty()) { delete items.back(); items.pop_back(); } |
,
1 2 3 4 5 | while (!items.empty()) { delete items.at(0); items.erase(items.begin()); } |
和
1 2 | while (!items.empty()) delete items.at(0); |
其中每一个都会因为某种原因而爆炸,包括删除已经删除的对象和超出范围的向量迭代器。
我该怎么办?我希望能够重用相同的向量,并在稍后向其中添加更多的项指针。仅仅使用
编辑:好的,我已经切换到共享模式了。现在我有
1 | vector<shared_ptr<Item> > items; |
然而,当我执行
我用你删除东西的所有方法做了一个测试,其中一个根本不起作用。有关它们的注释,请参见下面的代码。
要回答您的问题"我该怎么做",下面是我在删除时的错误:1)确保内存是我的(我知道相应的新内存在哪里吗)?2)确保我没有删除内存(如果删除了,即使是我的内存,现在也不会删除)。3)如果您很确定您的SEG错误是由代码的单个部分引起的,那么在另一个项目中将其分解为一个小测试用例(类似于您在问题中所做的那样)。然后玩它。如果您在一个小项目中运行代码示例,那么您会在最后一个项目中看到SEG错误,并且会注意到在其他每种情况下都会进行删除。像这样分解代码会让您知道您需要跟踪如何将这些存储在向量中,以查看您在哪里失去了它们的所有权(通过删除,或将它们传递给删除它们的某个对象,等等)。
旁注:正如其他人所说,如果您可以使用智能指针,它们将为您处理内存管理。但是,请继续您的研究,并了解如何使用愚蠢的指针。有时您不能导入Boost,或者让qt为您进行内存管理。此外,有时您必须将指针存储在容器中,因此也不要害怕这样做(即:qt开发人员强烈建议使用指针来存储小部件,而不是引用或任何类似的内容)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include <vector> using namespace std; class Item { public: int a; }; int main() { vector<Item *> data; for(int x = 0; x < 100; x++) { data.push_back(new Item()); } //worked for me, and makes sense for(int x = 0; x < 100; x++) { delete data.at(x); } data.clear(); for(int x = 0; x < 100; x++) { data.push_back(new Item()); } //worked for me, and makes sense while (!data.empty()) { delete data.back(); data.pop_back(); } data.clear(); for(int x = 0; x < 100; x++) { data.push_back(new Item()); } // //worked for me, and makes sense while (!data.empty()) { delete data.at(0); data.erase(data.begin()); } for(int x = 0; x < 100; x++) { data.push_back(new Item()); } // //This one fails, you are always trying to delete the 0th position in // //data while never removing an element (you are trying to delete deleted memory) // while (!data.empty()) // { // delete data.at(0); // } return 0; } |
好吧,我做到了。经过一段时间,大量的阿司匹林和大量的脱发,我终于明白了问题所在。原来我之前调用了一个特殊的析构函数,这个析构函数包含了这个指针向量的类。我不知道仅仅调用析构函数会导致它擦除所有静态数据成员。我有时讨厌C++。
听起来好像向量中重复了相同的指针。为了确保只删除一次,只需将它们转移到
1 2 3 4 5 6 7 8 | std::set<Item*> s( items.begin(), items.end() ); items.clear(); while ( !s.empty() ) { delete *s.begin(); s.erase( s.begin() ); } |
What do I do?
不要维护指针向量。实际上,这几乎总是一个错误,你正在与负责内存管理的向量(raii)的设计作斗争。现在您必须在每个指针上调用
你真的需要一个指针向量吗?如果您真的这样做了(不仅仅是认为您这样做了,而且它实际上是出于某种原因的需求),那么就使用智能指针。
向量会动态地为您分配内存,只需按照预期的方式使用它。
使用
使用这样的智能指针向量:
1 | vector<shared_ptr<Item> > myVect; |
或者使用Boost中的指针容器库。
可能有一种方法可以做到这一点,并且可以重复使用,但是它似乎很容易出错,而且要做更多的工作,特别是考虑到Boost中的指针容器是一个只包含头的库。