【问题标题】:How to retrieve invalidated iterator?如何检索无效的迭代器?
【发布时间】:2014-01-17 20:35:02
【问题描述】:

嗯,标题说明了一切。

我有这段代码:

std::list<vector<Plane>> list;
std::list<vector<Plane>>::iterator possible_planes_it;

...

for(possible_planes_it = list.begin(); possible_planes_it != 
    list.end(); possible_planes_it++)
{
        if(static_cast<float>(good_matches.size()) >= static_cast<float>((matches.size())*0.8))
        {
        if(possible_planes_it->back().getTimestamp() < count) // Means that there has not been a match found this round
        {
            possible_planes_it->push_back(Plane(area, *center_it, keypoint, descriptor, count));
            possible_planes_it->back().setNumberOfGoodMatches(good_matches.size());
        }
        else
        {
            if(possible_planes_it->back().getNumberOfGoodMatches() < good_matches.size())
            {
                possible_planes_it->pop_back(); // If a better match has been found, remove the last vector entry and push the new one
                possible_planes_it->push_back(Plane(area, *center_it, keypoint, descriptor, count));
                possible_planes_it->back().setNumberOfGoodMatches(good_matches.size());
            }
            else
            {
                list.push_back(vector<Plane>());
                list.back().push_back(Plane(area, *center_it, keypoint, descriptor, count));
            }
        }
    }
    else
    {
        list.push_back(vector<Plane>());
        list.back().push_back(Plane(area, *center_it, keypoint, descriptor, count));
    }
}

在这个 for 循环中的某个地方,我的迭代器变得无效,因此它陷入了无限循环。但是如何保持迭代器有效?

【问题讨论】:

  • 标题并没有说明一切。我们需要知道它是什么类型的容器。
  • 抱歉,更新了代码。它是一个向量列表。
  • 哪个迭代器失效了?看起来像列表中的迭代器?
  • 怎么知道迭代器无效?
  • 你真的必须发布所有代码来表达你的观点吗?

标签: c++ for-loop iterator


【解决方案1】:

您只需查看 cppreference.com 或 cplusplus.com 即可了解迭代器的有效性

基本上每次你 push_back 向量内的数据时,它都有可能被重新分配(除非你保留了足够的大小)。当向量被重新分配时,其元素的每个迭代器都会失效。

即使在插入/擦除元素时,列表元素的迭代器几乎总是有效(只有被擦除元素的迭代器变得无效)。

无限循环可能是您在每次迭代时向列表添加 1 个元素

{
    list.push_back(vector<Plane>());
    list.back().push_back(Plane(area, *center_it, keypoint, descriptor, count));
}

你必须证明这段代码永远不会使循环无限。只需在其中添加一个计数器并打印其值,然后添加一个计数器来计算循环次数并打印它。

基本上,如果您有指向 last-1 列表元素的迭代器,并且添加了一个元素,则 last-1 列表元素迭代器将成为 last-2 列表元素迭代器。

因此,您可能在开始时删除一个元素并在末尾添加一个元素,并且您对“结束”迭代器的检查变得像狗咬它的尾巴。

还有:

无效的迭代器将首先或稍后导致 seg-fault。 可能您的问题与迭代器有效性无关

也许你可以使用

list.push_front

?

更新已删除

【讨论】:

  • 你的更新没有意义,possible_planes_end 不是 typedef,它是一个变量。据推测,OP 将其设置在他的“...”部分。将其更改为 possible_planes.end 也不起作用,因为这不是有效的变量名。
  • 哦,伙计,讨厌不完整的 sn-ps,顺便说一下,如果没有代码显示那是什么,它在技术上仍然可以是宏 :D。
【解决方案2】:

std::list 以来,您的迭代器没有失效

    Addition, removal and moving the elements within the list
    or across several lists does not invalidate the iterators.
    An iterator is invalidated only when the corresponding
    element is deleted.

来自here
由于您没有删除任何元素,因此您的迭代器都不会失效。

发生的是你的'possible_planes_end'迭代器总是指向列表的末尾(即使在添加元素之后),所以你的问题可以减少到这个小sn-p:

   #include <list>

    int main()
    {
        std::list<float> l;
        std::list<float>::iterator i = l.begin(), end = l.end();
        do
        {
            l.push_back(1);
            i++;
        }while(i != end);
    }

这将永远运行,因为l 的大小在每个循环中不断增加一,i 一直指向倒数第二个元素。永远。

【讨论】:

  • 此代码将先或后结束,因为您没有擦除元素,因此会不断添加一个值(首先或稍后您将获得 std::bad_alloc)
  • @DarioOO 即使你的机器最终内存不足,如果这是唯一的停止条件,我认为很多人仍然认为这是一个无限循环。但是,是的,这实际上不会永远运行。
  • 循环在我的机器上给出一个 bad_alloc 需要 0.2 秒。我认为他既“删除”又“添加”节点,这在某种程度上是平衡的,循环真的永远持续
猜你喜欢
  • 1970-01-01
  • 2016-04-09
  • 2014-12-09
  • 1970-01-01
  • 2011-01-04
  • 2021-09-18
  • 1970-01-01
  • 2011-08-28
  • 2017-06-21
相关资源
最近更新 更多