从指针向量中删除东西

时间:2012-04-19 22:45:53

标签: c++ pointers vector

我有一个像这样的指针向量:

vector<Item*> items;

我想清除它。我试过了:

for (unsigned int i = 0; i < items.size(); i++)
    delete items.at(i);
items.clear();

while (!items.empty())
{
    delete items.back();
    items.pop_back();
}

while (!items.empty())
{
    delete items.at(0);
    items.erase(items.begin());
}

while (!items.empty())
    delete items.at(0);

由于某种原因,这些中的每一个都会爆炸,包括删除已删除的对象和超出范围的矢量迭代器。

我该怎么办?我希望能够重用相同的向量,并在以后添加更多的Item指针。只使用delete而不清除仍然留下垃圾指针,对吗?

编辑:好的,我已切换到shared_ptrs。现在我有了

vector<shared_ptr<Item> > items;

然而,当我items.clear();时,我得到错误“vector iterators incompatible”。我还在做什么错?

6 个答案:

答案 0 :(得分:2)

我用你所有删除内容的方式进行了测试,其中一个根本不起作用。请参阅下面的代码以获取对它们的评论。

要回答你的问题“我该怎么做”,这就是我在删除时出错的问题:
1)确保内存是我的(我知道相应的新内容)?
2)确保我没有删除内存(如果我这样做,即使它是我的,现在不是)。

3)如果您非常确定您的seg-fault是由代码的一个部分引起的,请将其分解为另一个项目中的小测试用例(有点像您在问题中所做的那样)。然后玩它。如果您已经在一个小项目中运行了代码示例,那么您可能会在最后一个上看到seg-fault,并且您会注意到删除工作在其他所有情况下都有效。像这样打破代码会让你知道你需要跟踪你在向量中存储这些代码的方式,看看你失去了对它们的所有权(通过删除,或者将它们传递给删除它们的东西等等......) )。

旁注:正如其他人所说,如果您可以使用智能指针,他们会为您处理内存管理。但是,请继续学习,并了解如何使用愚蠢的指针。有些时候你无法导入boost,或让QT为你做内存管理。此外,有时你必须在一个容器中存储指针,所以不要害怕这样做(IE:QT开发人员强烈建议使用指针来存储小部件而不是引用或任何类型)。

#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;
}

答案 1 :(得分:0)

使用这样的智能指针向量:

vector<shared_ptr<Item> > myVect;

或者在boost中使用Pointer Containers库。

可能有一种方法可以做到这一点并重复使用,但它似乎容易出错并且需要做更多工作,特别是考虑到boost中的Pointer Containers是一个仅限标题的库。

答案 2 :(得分:0)

使用boost::shared_ptr<Item>,当清除向量或删除元素时,它们将被删除。

答案 3 :(得分:0)

  

我该怎么办?

不要保持指针向量。实际上,它几乎总是一个错误,你正在与矢量(RAII)的设计作斗争,它为你负责内存管理。您现在必须在每个指针上调用delete

你真的需要一个指针向量吗?如果你真的做(不只是认为你这样做,但实际上是出于某种原因的要求),那么使用智能指针。

向量将为您动态分配内存,只需按原样使用它即可。

答案 4 :(得分:0)

听起来好像你在向量中重复了相同的指针。确保只删除它们,只需将它们转移到std::set并将其删除即可。例如,

std::set<Item*> s( items.begin(), items.end() );
items.clear();

while ( !s.empty() )
{
    delete *s.begin();
    s.erase( s.begin() );
}

答案 5 :(得分:0)

嗯,我做到了。经过很长一段时间,很多阿司匹林,以及很多失去的头发,我终于弄明白了问题是什么。事实证明我之前调用的是一个特定的析构函数,它包含了包含这个指针向量的类。我不知道只是调用析构函数会导致它擦除所有静态数据成员。我有时讨厌c ++。