首页 文章

删除std列表中的指针对象

提问于
浏览
3

我有一个 std::listEntity 个对象(屏幕上的对象) . 在一个类 EntityContainer 中,我有一个指向不同实体的指针列表 . 当 EntityContainer 被破坏时,我希望该列表中的所有实体也被破坏 . 我怎么能这样做,同时避免导致删除列表成员的迭代器错误?

EntityContainer::~EntityContainer()
{
    // Destroy children
    int numChildren = children.size();
    for (int i = 0; i < numChildren; i++)
    {
        Entity*& child = children.back();
        delete child;
    }
}

上面导致std :: list :: clear()中的空指针访问冲突,它在 EntityContainer 的销毁期间被调用,因为它是该对象的成员变量 . 我相信这是因为我删除了列表中的对象,所以当然删除它们时会尝试访问它们 . 但是,我的问题是,如果我只是保留它,并允许 clear() 列表而不显式删除其中的对象,则永远不会调用它们的析构函数 . 我只能假设这是因为列表只破坏列表中的指针,而不是指针指向的对象 . 这主要是作为假设 - 我可能是错的 . 你会怎么做?

4 回答

  • 11

    std::list<Entity *> 在销毁期间不会尝试访问任何指向的对象 .

    您的迭代删除代码显示错误 . 你应该做的只是循环遍历列表并删除所有内容:

    for(Entity *ptr : children) {
        delete ptr;
    }
    

    然后离开列表进行清理(取消分配内部指针列表) .

  • 0

    你的循环主要是因为这个错误

    int numChildren = children.size();
    for (int i = 0; i < numChildren; i++)
    {
        Entity*& child = children.back(); // this always returns the last element on the last, it does not remove it.  You are trying to delete an already deleted pointer
        delete child;
    }
    

    就像上面提到的那样,尝试类似的东西

    for(auto itr = children.begin(); itr != children.end(); ++itr)
    {
        Entity* child = *itr;
        delete child;
    }
    
  • 1

    假设 children 被定义为

    std::list<Entity *> children;
    

    你可以 delete 元素使用:

    for(auto&& child : children) {
      delete child;
    }
    children.clear(); // not really needed since this code is in the destructor
    

    这里没有问题使得任何迭代器无效,因为你实际上并没有从_1819524中删除任何元素,只是破坏了列表元素所指向的对象 . 在 for 语句完成后, list 仍将包含相同数量的元素,只有它们将在该点指向无效内存 .


    但是真的, don't use a container of raw pointers . 将 children 定义为

    std::list<std::unique_ptr<Entity>> children;
    

    然后你可以摆脱析构函数的定义 .

  • 2

    你的循环没有在列表中的每个指针上调用delete . 它只是在最后一个指针上重复调用delete . 这是您违反访问权限的原因 .

    delete 不会删除 list 中的任何内容,因为它对此一无所知 .

    你需要做点什么

    for(auto itr = children.begin(); itr != children.end(); ++itr)
    {
        Entity* child = *itr;
        delete child;
    }
    

    或者无论你喜欢什么样的循环语法 .

    或者,您可以将其设置为 list list ,以便在清除列表或删除条目时自动管理释放 .

相关问题