草庐IT

c++ - vector::erase 和 std::remove_if 的奇怪行为,其结束范围不同于 vector.end()

coder 2023-11-16 原文

我需要从 std::vector 的中间移除元素。

所以我尝试了:

struct IsEven {
    bool operator()(int ele)
    {
        return ele % 2 == 0;
    }
};

    int elements[] = {1, 2, 3, 4, 5, 6};
    std::vector<int> ints(elements, elements+6);

    std::vector<int>::iterator it = std::remove_if(ints.begin() + 2, ints.begin() + 4, IsEven());
    ints.erase(it, ints.end());

在此之后,我希望 ints vector 具有:[1, 2, 3, 5, 6]。

在 Visual Studio 2008 的调试器中,在 std::remove_if 行之后,修改了 ints 的元素,我猜我正在做某种事情这里有未定义的行为。

那么,如何从 vector 的范围中删除元素?

最佳答案

编辑:抱歉,这个的原始版本不正确。固定。

这是正在发生的事情。您对 remove_if 的输入是:

1  2  3  4  5  6
      ^     ^
    begin  end

并且 remove_if 算法查看 beginend 之间的所有数字(包括 begin,但不包括 end), 并删除与您的谓词匹配的所有元素。所以在 remove_if 运行之后,你的 vector 看起来像这样

1  2  3  ?  5  6
      ^  ^
  begin  new_end

? 是一个我认为不是确定性的值,尽管如果保证它是任何值,它将是 4new_endstd::remove_if 返回的内容,它指向您给它的输入序列的新结尾,现在删除了匹配元素。请注意,std::remove_if 不会触及您提供的子序列之外的任何内容。对于更扩展的示例,这可能更有意义。

说这是你的输入:

1  2  3  4  5  6  7  8  9  10
      ^              ^
    begin           end

std::remove_if 之后,你得到:

1  2  3  5  7  ?  ?  8  9  10
      ^        ^
    begin      new_end

想一想。它所做的是从子序列中删除 4 和 6,然后将子序列中的所有内容 向下移动以填充删除的元素,然后移动 end 迭代器到同一子序列的新末端。目标是满足其生成的 (begin, new_end] 序列与 (begin, end] 您传入的子序列,但删除了某些元素。您传入的 end 处或之后的任何内容都保持不变。

然后,您想要摆脱的是返回的结束迭代器和您给它的原始结束迭代器之间的所有内容。这些是 ?“垃圾”值。所以你的删除调用实际上应该是:

ints.erase(it, ints.begin()+4);

您刚才调用的 erase 会删除执行删除操作的子序列末尾以外的所有内容,这不是您想要的。

让事情变得复杂的是 remove_if 算法实际上并没有在 vector 上调用 erase(),也没有在任何时候改变 vector 的大小。它只是移动元素并在您要求它处理的子序列结束后留下一些“垃圾”元素。这看起来很愚蠢,但 STL 这样做的全部原因是为了避免 doublep 带来的无效迭代器的问题(并且能够在不是 STL 容器的东西上运行,比如原始数组)。

关于c++ - vector::erase 和 std::remove_if 的奇怪行为,其结束范围不同于 vector.end(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2717012/

有关c++ - vector::erase 和 std::remove_if 的奇怪行为,其结束范围不同于 vector.end()的更多相关文章

  1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  2. ruby-on-rails - `a ||= b` 和 `a = b if a.nil 之间的区别? - 2

    我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行

  3. ruby - ruby 中有 each_if 吗? - 2

    假设我在Ruby中有这个each循环。@list.each{|i|putsiifi>10breakend}我想循环遍历列表直到满足条件。这让我感到“不像Ruby”,因为我是Ruby的新手,是否有Ruby方法可以做到这一点? 最佳答案 您可以使用Enumerable#detect或Enumerable#take_while,取决于您想要的结果。@list.detect{|i|putsii>10}#Returnsthefirstelementgreaterthan10,ornil.正如其他人所指出的,更好的风格是先进行子选择,然后再对其

  4. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  5. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  6. ruby-on-rails - rails : check if the model was really saved in after_save - 2

    ActiveRecord用于在每次调用保存方法时调用after_save回调,即使模型没有更改并且没有生成插入/更新查询也是如此。这实际上是默认行为。在大多数情况下这没问题。但是一些after_save回调对模型是否实际保存的事情很敏感。有没有办法确定模型是否实际保存在after_save中?我正在运行以下测试代码:classStage 最佳答案 ActiveRecordusetocallafter_savecallbackeachtimesavemethodiscalledevenifthemodelwasnotchangedan

  7. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  8. ruby - 在 Ruby 的 if 语句中检查 bash 命令 - 2

    如何在Ruby的if语句中检查bash命令的返回值(true/false)。我想要这样的东西,if("/usr/bin/fswscell>/dev/null2>&1")has_afs="true"elsehas_afs="false"end它会提示以下错误含义,它总是返回true。(irb):5:warning:stringliteralincondition正确的语法是什么?更新:/usr/bin/fswscell寻找afs安装和运行状态。它会抛出这样的字符串,Thisworkstationbelongstocell如果afs没有运行,命令以状态1退出 最

  9. ruby - 变量赋值后的 if 语句 - 有多常见? - 2

    我最近与一位同事讨论了以下Ruby语法:value=ifa==0"foo"elsifa>42"bar"else"fizz"end我个人并没有看到太多这种逻辑,但我的同事指出,这实际上是一种相当普遍的Rubyism。我试着用谷歌搜索这个主题,但没有找到任何文章、页面或SO问题来讨论它,这让我相信这可能是一种非常实际的技术。然而,另一位同事发现语法令人困惑,而是将上面的逻辑写成这样:ifa==0value="foo"elsifa>42value="bar"elsevalue="fizz"end缺点是value=的重复声明和隐式elsenil的丢失,如果我们想使用它的话。这也感觉它与Ruby

  10. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

随机推荐