1

可能重复:
STL 删除没有按预期工作?

抱歉,我是 C++11 和迭代器的新手。这应该删除数组中的所有数字 3,但不会删除最后一个。为什么?

#include <algorithm>
#include <array>
#include <iostream>

int main() {

   std::array<int, 8> a{{9, 3, 4, 5, 33, 5, 6, 3}};

   int N(3);

   std::remove(a.begin(), a.end(), N);

   for (int i : a) {
      std::cout << i << '\n';
   }

}

我得到输出:

{ 9, 4, 5, 33, 5, 6, 6, 3 }
                        ^
                        |
             // the last 3 is still there
4

3 回答 3

6

std::remove对迭代器进行操作;因此,它无法真正从容器中删除元素。这就是为什么它通常与erase

a.erase(std::remove(a.begin(), a.end(), N), a.end());

正如其他人所指出的,这不适用于array.

于 2012-12-30T20:51:07.220 回答
6

算法不了解底层容器。它们只是根据给定的迭代器进行迭代,并独立于容纳它们的容器访问元素。这就是为什么有一种叫做erase-remove idiom的东西,它采用以下模式:

container.erase(std::remove(it1, it2, value), std::end(container));

std::remove将保留的元素移动到前面(感谢 K-ballo)并将迭代器返回到未移动元素的开头。然后,erase从那一刻到最后,抹去一切。

由于std::array封装了一个固定大小的数组,我会将您的示例修改为std::vector

std::vector<int> v{9, 3, 4, 5, 33, 5, 6, 3};
v.erase(std::remove(std::begin(v), std::end(v), 3), std::end(v));

唯一需要注意的是 and 的更一般形式.begin().end()它也适用于内置数组。这包含在 C++11 中。

于 2012-12-30T20:51:17.587 回答
2

正如其他人指出的那样,std::remove()不会删除任何元素。如果你需要使用std::array<...>你仍然可以使用std::remove()并且只是捕获相应的迭代器来确定序列的结束。我不知道您如何获得声称的输出(带有花括号和逗号),但这是我将如何实现它:

auto end = std::remove(a.begin(), a.end(), 3);
std::cout << "{ ";
if (a.begin() != end) {
    std::copy(a.begin(), end - 1, std::ostream_iterator<int>(std::cout, ", "));
    std::cout << end[-1];
}
std::cout << "}\n";
于 2012-12-30T21:02:32.547 回答