0

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

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();,我收到错误“向量迭代器不兼容”。我还在做错什么?

4

6 回答 6

2

我用你所有的删除方法进行了测试,其中一种根本不起作用。有关它们的评论,请参见下面的代码。

要回答您的问题“我该怎么做”,这是我在删除时发生段错误时所做的事情:
1)确保内存是我的(我知道相应的新内存在哪里)?
2)确保我没有删除内存(如果我删除了,即使它是我的,现在也不是)。

3)如果你很确定你的段错误是由你的代码的一个部分引起的,把它分解成另一个项目中的一个小测试用例(就像你在你的问题中所做的那样)。然后玩它。如果您在一个小项目中运行代码示例,您会在最后一个项目中看到 seg-fault,并且您会注意到删除在其他所有情况下都有效。像这样分解代码会让你知道你需要跟踪你是如何将这些存储在你的向量中的,以查看你在哪里失去了它们的所有权(通过删除,或者将它们传递给删除它们的东西,等等...... )。

附注:正如其他人所说,如果您可以使用智能指针,他们会为您处理内存管理。但是,请继续在这里学习并了解如何使用愚蠢的指针。有时您无法导入 boost,或者让 QT 为您进行内存管理。此外,有时您必须将指针存储在容器中,因此也不要害怕这样做(即: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;
}
于 2012-04-19T23:13:06.070 回答
0

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

vector<shared_ptr<Item> > myVect;

或者使用 boost 中的指针容器库。

可能有一种方法可以做到这一点并重用东西,但它似乎容易出错并且需要做更多的工作,特别是考虑到 boost 中的指针容器是一个仅头文件的库。

于 2012-04-19T22:49:47.030 回答
0

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

于 2012-04-19T22:50:01.370 回答
0

我该怎么办?

不要维护指针向量。确实,这几乎总是一个错误,并且您正在与为您处理内存管理的向量 (RAII) 的设计作斗争。您现在必须调用delete每个指针。

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

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

于 2012-04-19T22:50:18.983 回答
0

听起来好像您的向量中重复了相同的指针。为了确保您只删除它们一次,只需将它们转移到 astd::set并在那里删除它们。例如,

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

while ( !s.empty() )
{
    delete *s.begin();
    s.erase( s.begin() );
}
于 2012-04-19T23:15:17.767 回答
0

嗯,我做到了。用了很多时间,吃了很多阿司匹林,掉了很多头发,我终于弄清楚了问题所在。原来我之前调用了一个特定的析构函数,它包含包含这个指针向量的类。我不知道仅调用析构函数会导致它擦除所有静态数据成员。我有时讨厌 c++。

于 2012-04-24T20:27:00.083 回答