C++ STL如何在erase()之后保存迭代器

C++ STL如何在erase()之后保存迭代器,c++,stl,C++,Stl,我想处理向量容器中的每个节点 假设向量包含0、1、2和3,迭代器指向2 我想在不丢失迭代器位置信息的情况下删除2,因为我想在删除2之后处理“3” 下面是我所做的,但是输出没有显示我的意图 以下是我的问题: Q1)当vector::iterator oldIter=iter时被执行, oldIter是否创建新的迭代器对象 Q2)为什么迭代器的值在递增后保持不变 Q3)擦除节点而不丢失数据的好方法是什么 迭代器的位置 问题4)最后,一个无关紧要的问题。我试过了 当vector::iterator o

我想处理
向量
容器中的每个节点

  • 假设向量包含0、1、2和3,迭代器指向2

  • 我想在不丢失迭代器位置信息的情况下删除2,因为我想在删除2之后处理“3”

  • 下面是我所做的,但是输出没有显示我的意图

  • 以下是我的问题:

  • Q1)当
    vector::iterator oldIter=iter时被执行,
    
    oldIter
    是否创建新的迭代器对象

    Q2)为什么迭代器的值在递增后保持不变

    Q3)擦除节点而不丢失数据的好方法是什么 迭代器的位置

    问题4)最后,一个无关紧要的问题。我试过了 当
    vector::iterator oldIter=iter时被执行,oldIter是否执行
    创建一个新的迭代器对象

    为什么迭代器的值在递增后保持不变 是吗

    没有。是什么让你得出这样的结论?您的
    printf
    语句?那些是无效的
    printf
    不知道如何处理向量迭代器。您对它的调用是未定义的行为

    在不丢失节点位置的情况下擦除节点的好方法是什么 迭代器

    捕获
    erase
    调用的返回值

    iter = vContainer.erase(iter);
    
    最后,一个无关紧要的问题。我试过了 当
    vector::iterator oldIter=iter时被执行,oldIter是否执行
    创建一个新的迭代器对象

    为什么迭代器的值在递增后保持不变 是吗

    没有。是什么让你得出这样的结论?您的
    printf
    语句?那些是无效的
    printf
    不知道如何处理向量迭代器。您对它的调用是未定义的行为

    在不丢失节点位置的情况下擦除节点的好方法是什么 迭代器

    捕获
    erase
    调用的返回值

    iter = vContainer.erase(iter);
    
    最后,一个无关紧要的问题。我尝试过cout理想情况下,不要单独删除节点。相反,将
    std::remove_if()
    std::vector::erase()
    结合使用:这将潜在的二次算法转化为线性算法。也就是说,你会用这样的东西

    vContainer.erase(std::remove_if(vContainer.begin(),
                                    vContainer.end(),
                                    [](int value){ return someCondition(value); }),
                                   vContainer.end());
    
    否则,最简单的方法可能是仅使用偏移恢复位置:

    int offset(std::distance(vContainer.begin(), it));
    vContainer.erase(it);
    it = vContainer.begin() + offset;
    
    由于
    erase(it)
    将移动位置
    it
    之后的所有对象,因此成本相当高。使用像
    std::remove_if()
    这样的算法,最多只聚合更改并移动每个元素一次,而不是每次
    erase()
    移动一次,这样的算法效率要高得多

    针对您的具体问题:

  • std::vector::iterator oldIter=iter
    显然创建了
    iter
    的副本。但是,请注意,当使用
    erase(it)
    时,引用
    it
    引用的对象或该对象之后的所有迭代器都将无效
  • 当递增迭代器时,它不会停留在同一位置。如果您认为是这样,那么您可能错误地确定了迭代器的位置。确定随机访问迭代器的迭代器位置的最佳方法是获取从序列开始的偏移量,例如,使用
    std::distance(v.begin(),it)
    (假设
    it
    是范围
    v.begin()
    v.end()
    的迭代器)
  • 只需保留从起点开始的偏移量并将其恢复即可
  • 迭代器无法打印。他们的价值毫无意义。使用
    printf()
    打印某些内容并不意味着什么,因为类型
    %x
    只能用于整数值,并且在特定位置与其他类型一起使用它是未定义的行为。请参见上文如何获得迭代器位置的合理指示。请注意,
    std::distance(v.begin(),it)
    的结果是某种积分类型:最好使用IOStreams打印它,IOStreams会自动计算出类型,而不是猜测
    printf()的格式说明符的类型
  • 理想情况下,不要单独删除节点。相反,将
    std::remove_if()
    std::vector::erase()
    结合使用:这将潜在的二次算法转化为线性算法。也就是说,你会用这样的东西

    vContainer.erase(std::remove_if(vContainer.begin(),
                                    vContainer.end(),
                                    [](int value){ return someCondition(value); }),
                                   vContainer.end());
    
    否则,最简单的方法可能是仅使用偏移恢复位置:

    int offset(std::distance(vContainer.begin(), it));
    vContainer.erase(it);
    it = vContainer.begin() + offset;
    
    由于
    erase(it)
    将移动位置
    it
    之后的所有对象,因此成本相当高。使用像
    std::remove_if()
    这样的算法,最多只聚合更改并移动每个元素一次,而不是每次
    erase()
    移动一次,这样的算法效率要高得多

    针对您的具体问题:

  • std::vector::iterator oldIter=iter
    显然创建了
    iter
    的副本。但是,请注意,当使用
    erase(it)
    时,引用
    it
    引用的对象或该对象之后的所有迭代器都将无效
  • 当递增迭代器时,它不会停留在同一位置。如果您认为是这样,那么您可能错误地确定了迭代器的位置。确定随机访问迭代器的迭代器位置的最佳方法是获取从序列开始的偏移量,例如,使用
    std::distance(v.begin(),it)
    (假设
    it
    是范围
    v.begin()
    v.end()
    的迭代器)
  • 只需保留从起点开始的偏移量并将其恢复即可
  • 迭代器无法打印。他们的价值毫无意义。使用
    printf()
    打印某些内容这一事实并不意味着什么,因为类型
    %x
    只能用于整数值并使用不同的类型