【问题标题】:remove not working correctly删除无法正常工作
【发布时间】:2011-06-14 10:55:51
【问题描述】:
std::vector<int> v = {1,2,3,4,5};
auto i = std::remove(v.begin(),v.end(),3); 
for(auto j = v.begin(); j!= v.end();++j)
   std::cout << *j;

实际输出:12455

额外的 5 个从何而来?

所需输出:1245

如何达到同样的效果?

我其实是想改变向量的大小,Prasoon saurav 给出的答案看起来是正确的

【问题讨论】:

    标签: c++ algorithm templates stl c++11


    【解决方案1】:

    remove doesnt actually remove the elements

    Remove 从范围[first, last) 中删除所有等于value 的元素。也就是说,remove 返回一个迭代器new_last,使得[first, new_last) 范围内不包含等于value 的元素。 1 [new_last, last) 范围内的迭代器都仍可取消引用,但它们指向的元素未指定。 remove是稳定的,也就是说不等于value的元素的相对顺序不变。`

    std::remove 算法仅使用一对前向迭代器工作,通常对底层容器一无所知。

    您需要使用erase-remove 成语实际上 删除元素,即将eraseremove 结合

    auto i = std::remove(v.begin(),v.end(),3);
    v.erase(i,v.end());
    for(auto j = v.begin(); j!= v.end();++j)
       std::cout << *j;
    

    【讨论】:

    • @Rookie:再看看remove() 的电话。该算法看到一个序列并且无法访问容器,那么它如何从中删除任何东西呢?
    • “擦除删除习语” - 在页面末尾的“注释”中给出。
    • @GMan:我的意思是支持你的回答并删除我上面的​​评论。你为什么删除你的答案?它包含了 Prasoon 尚未提出的重要观点。
    • @sbi:我必须同意 Prasoon 的观点。问题很清楚,他希望操作后的容器不包含最后一个元素(重复 5)。我认为这个问题/答案将来不会被任何人误解。问题清晰而准确,答案是正确的。另外,我不希望看到容器末尾留下的元素只是为了节省几个 CPU 周期...... 99.99% 的时间不需要微优化,只是将其发布在答案中可能会让人相信这是值得的。
    • @David:但区别很重要,我同意@sbi 的观点,即 OP 应该意识到这一点。我想说,任何能促使人们更好地理解他们正在使用的图书馆的事情都是一件好事。
    【解决方案2】:

    for() 语句中打印向量的 n+1 位置是接缝。 应该是:

    for(auto j = v.begin(); j!= v.end();j++)
       std::cout << *j;
    

    j++没有++j

    【讨论】:

    • for 循环的上下文中,j++++j 是等价的(尽管对于迭代器,可能存在性能差异)。
    • 在这种情况下,j++++j 会产生相同的行为。
    【解决方案3】:

    再次阅读std::remove 的文档。

    该函数不会从容器中移除元素(事实上,它甚至不知道涉及到容器,因为它只看到迭代器),它只是按顺序移动值并返回一个新的迭代器 i 使得所有区间 [ begin .. i [ 包含原始顺序中的所有未删除元素。 [ i .. end [ 中剩余的元素未指定,您有责任从容器中消除该间隔(如果需要):

    auto i = std::remove(...);
    v.erase(i,v.end());
    

    您有一个额外的5 的原因是典型的删除算法将值复制 到删除值留下的孔中,并且由于超过i 迭代器的值永远不会被覆盖,它们仍然存在和原来的顺序一样。然而,这种行为并不可靠 - 只需消除超过 i 的值而不读取它们。

    【讨论】:

      【解决方案4】:

      remove 返回 new 结尾。所以你的代码的修复是这样的:

       std::vector<int> v = {1,2,3,4,5};
       auto newEnd = std::remove(v.begin(),v.end(),3);//return value stored in newEnd
       for(auto j = v.begin(); j!= newEnd ;++j) //note j!=newEnd
           std::cout << *j;
      

      输出:

      1245
      

      自己检查一下:http://www.ideone.com/3AMD9

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多