迭代多个std列表并在它们之间移动对象

时间:2015-01-07 00:48:06

标签: c++

我正在模拟一个网络,在每个节点我有一个主列表,根据输入此列表的对象,我处理这个对象,之后我将它推入另一个列表或删除它。 我的算法的伪代码如下所示:

for (iter = WBRequests.begin(); iter != WBRequests.end() ; iter++) {

    // 1- process the object
    // 2- check the second list
    for (iterSer = ServedRequests.begin(); iterSer != ServedRequests.end();iterSer++) {

        //if the *iter object satisfy some condition
        if (  (*iterser)->getIsACKok() )
            break;
    }

    if (iterSer != ServedRequests.end())
    {
        // do something and push into the list
        ServedRequests.push_back(*iter);

        iter  = WBRequests.erase(iter );
        iterSer = ServedRequests.erase(iterSer);

    }
    else { //No corresponding  object

        ServedRequests.push_back(*iter);
        iter  = WBRequests.erase(iter );
    }
}

我有两个问题:

  1. 我什么时候需要删除迭代器iter和iterSer。
  2. 在模拟开始时,ServedRequests列表只包含一个对象,所以 可能我需要的对象是列表的结尾。当我使用

    时,如何获得此对象
         if (iterSer != ServedRequests.end())
    

    编辑: 所有请求都是指向对象的指针,区别在于对象的属性。

    1-当新请求进入节点时,它被推入主列表中, 根据对象的类型(设置,确认或释放)我 处理此对象,然后将其插入服务列表并删除它 从主要清单。

    2-例如,每个节点发送一个设置数据包,在主列表中推送,处理它,以及
    将其存储在服务列表中。当数据包确认到达主列表时,我需要 检查相应的设置包是否在这里。同样的 发布数据包。

    3-开头,每个节点中的服务列表有1个设置数据包和1个确认 数据包,当释放数据包到达时,我需要迭代整个列表(稍后我 将在服务列表中有模式包)

2 个答案:

答案 0 :(得分:1)

  1. 假设您的代码不是多线程的(否则它将无效)。
  2. 如果要使迭代器无效并从列表中明确删除其元素,则删除迭代器,通常是将其删除到另一个列表中删除它。

  3. 我不明白你需要什么。如果您有1个对象,只需使用list.begin()即可获得它。如果你需要列表的最后一个对象,你可以--list.end(),但前提是你有一个双向链表(“operator - ”不适用于“forward_list”)

  4. 奖励点:

    你正在做iter++iterServ++,但这是不必要的,因为你已经将迭代器带到了下一个元素

    iter  = WBRequests.erase(iter ); //erase Element1 and returns Element2
    //if you do iter++...
    iter++;               //... now iter is pointing to Element3 (you skipped Element2!)
    

    没有进一步的细节,我无能为力:

    • 请求在节点中出现并在第二个节点中死亡,是否与第一个节点相连?
    • “外部”是否会创建请求? (因为这是一个网络,它也可能是在处理节点时它会产生更多的请求。
    • 是否需要多线程?
    • 每个节点是否只有请求和服务列表而不与其他节点通信?

    请记住网络是图形,因此您有许多节点,每个节点都连接到许多其他节点。

    编辑:

    可能不需要的行为是由“擦除”引起的。因为当你调用erase时你已经将迭代器推进1,所以不需要再次执行它。

    for (iter = WBRequests.begin(); iter != WBRequests.end() ; ) //no increment here
    for (iterSer = ServedRequests.begin(); iterSer != ServedRequests.end(); )  // no increment here
    
        //...
    
        //when you erase both no need to increment
        iter  = WBRequests.erase(iter );
        iterSer = ServedRequests.erase(iterSer);
    
        //...
    
        //do not increment iterSer since its already ended
        iter  = WBRequests.erase(iter );
    

答案 1 :(得分:1)

  
      
  1. 我什么时候需要删除迭代器iter和iterSer。
  2.   

当您不想再使用它时删除。我认为问题是:std::list::erase返回最后一个删除元素后的迭代器,它只是一个返回值,而不是一个强制输入参数。那么你真的需要将返回的值分配给iter或iterServ吗? 每当循环中有erase个操作时,请在for中处理您的更改条件,因为当erase成功时它可能会跳过1个元素。

  
      
  1. if(iterSer!= ServedRequests.end())
  2.   

我不认为这是一个问题。 ServedRequests.end()返回容器的最后一个元素之后的元素的迭代器。http://en.cppreference.com/w/cpp/container/list/end开头,ServedRequests有1个对象,for循环中的行将被执行1次