【问题标题】:std::list - removing elements [duplicate]std::list - 删除元素 [重复]
【发布时间】:2018-06-14 13:33:15
【问题描述】:

我目前在我的应用程序中使用 std::list 并尝试解决超出范围的问题。

我确实需要在迭代时在一个对象的方法中使用 pop_back。我认为它可能会以某种方式改变 std::list::end 。有没有可能让它正常工作?这段代码应该和这个类似:

编辑:我使用的是 GCC 6.1

编辑 2:如果您遇到与 reverse_iterator 相关的相同问题,我建议您尽可能重新设计应用程序并使用临时迭代器。更直观。

#include <list>

struct Object;

std::list<Object*> list;

struct Object
{
    Object(bool state) : state(state) {}
    bool state;
    void method()
    {
        if(state) list.pop_back();
    }
};


int main()
{
    list.push_back(new Object(false));
    list.push_back(new Object(true));
    list.push_back(new Object(false));
    for(auto it = list.rbegin(); it != list.rend(); ++it)
    {
        (*it) -> method();
    }
    return 0;
}

【问题讨论】:

  • 我正在关闭它缺少 MCVE。从 cmets 可以明显看出,问题是特定于特定编译器的,这里的示例并不完整。需要完整的细节。
  • @SergeyA 我不太确定。我已经链接到另一个具有类似问题的问题,该问题声称迭代器失效规则对于反向迭代器是不同的。
  • 示例已完成。它抛出异常,这实际上是我的问题。
  • @AkasataAkasata 行为似乎取决于编译器和版本。请在问题中添加您的编译器、版本和编译标志。
  • 我已经编辑了帖子。编译器是 GCC 6.1。

标签: c++ stdlist outofrangeexception


【解决方案1】:

只有当您正在弹回您正在访问的最后一个(首先使用您的反向迭代器)元素时,这才应该是一个问题。这是因为您正在递增被 pop_back() 无效的迭代器

如果是这种情况,一种解决方案是先增加迭代器,存储结果,然后调用method()

【讨论】:

  • 另一种方法是调用erase,这将为您提供一个有效的迭代器或指向结束元素的迭代器。然后可以检查返回的迭代器是否为end(),否则调用方法。
【解决方案2】:

问题是it 在您调用pop_back() 的那一刻无效,导致您尝试使用它时出现未定义的行为。您应该在调用您的方法之前存储下一步:

for(auto it = list.rbegin(); it != list.rend();)
{
    auto itr = it++; 
    (*itr) -> method();
}

【讨论】:

  • 我不清楚为什么it 无效。 std::list::pop_back() 只会使擦除元素的迭代器无效。
  • 我也弄不明白。此循环中不使用已擦除的元素。
  • @FrançoisAndrieux 你说得对,当前显示的代码只会在第二个元素上弹出一次,这意味着it 已经通过了它。我忽略了这一点。尽管如此,我认为 OP 没有显示准​​确的代码,实际代码正在尝试删除最后一个元素。当前代码运行良好。
  • @RickAstley 我自己尝试时遇到了同样的问题。这似乎与具有不同失效规则的反向迭代器有关,因为使用 beginend 不会导致问题,
  • 我使用的是 gcc 6.1
猜你喜欢
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-15
  • 2014-09-27
相关资源
最近更新 更多