【问题标题】:Don't understand results of std::remove in C++ STL不理解 C++ STL 中 std::remove 的结果
【发布时间】:2013-09-26 20:32:13
【问题描述】:

我正在阅读 Josuttis “C++ 标准库,第 2 版。”。在第 6.7.1 节中,作者解释说下面给出的代码会产生意想不到的结果。我仍然不知道std::remove() 的功能,以及为什么我会得到这个奇怪的结果。 (虽然我知道您需要使用std::erase() 才能实际删除元素,实际上最好使用list::erase() 而不是std::remove() 和`std::remove() 的组合)。

list<int> coll;
// insert elements from 6 to 1 and 1 to 6
for (int i=1; i<=6; ++i) {
     coll.push_front(i);
     coll.push_back(i);
}

// print
copy (coll.cbegin(), coll.cend(), // source
      ostream_iterator<int>(cout," ")); // destination
      cout << endl;

// remove all elements with value 3
remove (coll.begin(), coll.end(), // range
        3); // value
// print (same as above)   

结果是

pre:  6 5 4 3 2 1 1 2 3 4 5 6
post: 6 5 4 2 1 1 2 4 5 6 5 6 (???) 

【问题讨论】:

  • 删除后如何打印?
  • @KarolyHorvath,我刚刚添加了代码!查看打印功能
  • 在这里查看答案:stackoverflow.com/questions/6456870/…
  • 所有值为 3 的元素都被以下元素覆盖。没看到图吗?
  • @newprint 另请注意,在您的情况下,调用list::removefar better,而不是使用擦除删除习语。

标签: c++ c++11 stl


【解决方案1】:

这个explanation 应该有帮助:

删除是通过以这种方式移动范围内的元素来完成的 要擦除的元素被覆盖。的相对顺序 保留的元素和物理大小的 容器不变。指向元素之间的迭代器 范围的新逻辑端和物理端仍然是 可取消引用,但元素本身具有未指定的值。 调用 remove 之后通常会调用容器的 擦除方法,它擦除未指定的值并减少 容器的物理大小以匹配其新的逻辑大小。

注意std::remove() 的返回值是代表新的end 的迭代器。因此,在这个新端和旧端调用std::erase() 将释放你多余的空间。

【讨论】:

  • 几乎是正确的——如果你只用新的结尾调用erase,它只会删除一个元素。您需要调用双参数版本,新端和旧端。
【解决方案2】:

std::remove 实际上并没有缩短列表。它不能——因为它只获取迭代器而不是容器本身。

它所做的是复制剩余的值,以便您在容器的开头获取它们。但是容器的最终元素(在你的情况下 - 最后两个:'5'和'6')实际上仍然存在..

在使用std::remove 之后,您必须自行缩短到容器以删除剩余的“垃圾”副本。

【讨论】:

    【解决方案3】:

    您要求算法删除“3”元素。因此,在枚举容器时,如果从中间移除某些东西,算法会改变内容。在您的情况下,这种转变发生了 2 次,这就是为什么您会在末尾看到“5 6”元素(因为实际末尾已向前移动到 2 个项目)。然后,“std::erase”将解决尾部僵尸的问题。

    【讨论】:

      【解决方案4】:

      引用everyone's favorite c++ website

      该函数不能更改包含 元素范围(即,它不能改变数组的大小或 container):删除是通过替换比较的元素来完成的 下一个不等于 val 的元素,并发出新的信号 通过将迭代器返回到元素来缩短范围的大小 这应该被认为是它的新的过去的元素。

      所以std::remove 不会改变列表的大小。它删除匹配的元素并返回一个表示列表新结尾的迭代器。要真正删除无关元素,您需要执行以下操作:

      auto it = remove(coll.begin(), coll.end(), 3);
      coll.erase(it, coll.end());
      

      【讨论】:

        猜你喜欢
        • 2013-09-19
        • 2017-01-28
        • 1970-01-01
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 2021-10-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多