【问题标题】:removing things from a pointer vector从指针向量中删除东西
【发布时间】:2012-04-19 22:45:53
【问题描述】:

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

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

【问题讨论】:

  • 如果您有一个指针向量,请使用智能指针(无论如何您都应该这样做)。
  • 除了最后一个之外,它们似乎都还可以。您遇到了什么问题?
  • 自 C++11 起就有 std::weak_ptrstd::unique_ptrstd::shared_ptr。他们弃用了 C++03 std::auto_ptr
  • 您需要绝对确定您确实想要将指针(或智能指针)而不是对象本身存储到您的容器中(在本例中为向量)。如果不需要,请不要这样做。阅读这些问题:stackoverflow.com/questions/2693651/…stackoverflow.com/questions/141337/…

标签: c++ pointers vector


【解决方案1】:

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

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

3) 如果你很确定你的 seg-错误是由您的代码的一个部分引起的,将其分解为另一个项目中的一个小测试用例(就像您在问题中所做的那样)。然后玩它。如果您在一个小型项目中运行代码示例,您会在最后一个项目中看到 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;
}

【讨论】:

    【解决方案2】:

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

    vector<shared_ptr<Item> > myVect;
    

    或者在 boost 中使用Pointer Containers 库。

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

    【讨论】:

    • 嗯,现在我将如何清除该向量?我现在有 vector&lt;shared_ptr&lt;Item&gt; &gt; items; ,当我做 items.clear(); 时,我得到的错误是“向量迭代器不兼容”。
    【解决方案3】:

    使用boost::shared_ptr&lt;Item&gt;,当vector被清空或元素被删除时,它们将被删除。

    【讨论】:

      【解决方案4】:

      我该怎么办?

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

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

      vector 会为你动态分配内存,只要按原意使用即可。

      【讨论】:

        【解决方案5】:

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

        std::set<Item*> s( items.begin(), items.end() );
        items.clear();
        
        while ( !s.empty() )
        {
            delete *s.begin();
            s.erase( s.begin() );
        }
        

        【讨论】:

          【解决方案6】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-07-02
            • 2014-04-28
            • 1970-01-01
            • 2013-09-24
            • 2012-08-12
            • 2015-08-09
            • 1970-01-01
            相关资源
            最近更新 更多