erase()
和remove()
之间有什么区别?
std::whatever::erase
-采用范围迭代器(倒数第一),并匹配所有元素std::remove
-获取范围迭代器(倒数第一)和一个要匹配的值以进行删除
除此之外,他们似乎也在做同样的事情。即实际的"擦除"或"删除"在这两种情况下都是相同的(除非我弄错了)。那么,为什么其中一个是方法(向量、集合、映射等),另一个是自由浮动函数呢?
注:
- 是的,我知道还有一个
erase()
需要一个迭代器,但你也可以有一个具有相同语义的std::remove()
擦除或删除与不同。
erase
实际上是从集合中删除项目。
std::remove
使集合的大小与开始时相同,但会压缩集合中的项,因此那些具有要删除的值的项会被集合中具有其他值的值覆盖。
换言之,如果您从1, 2, 1, 3
开始,并执行remove(..., 1)
,那么您最终会得到一个包含2, 3, x, x
的集合,其中x
表示某个未知值(可能是一个移动的值,因此如果它们是字符串,则可能会变成空字符串)。
完成后,它将迭代器返回到第一个x
的位置。如果您想真正从集合中删除这些项目,那么可以调用collection.erase(returned_iterator, collection.end())
(也称为删除/擦除习惯用法)。
如果您关心为什么会这样,原因之一是std::remove
可以使用迭代器。迭代器允许访问容器中的元素,但不允许访问周围的容器本身。因此,std::remove
不可能从容器中擦除元素,即使对于支持(并非所有容器都这样做)的容器也是如此。
std::remove
实际上并没有销毁容器中的元素。相反,它"re移动"范围中满足特定条件的所有元素,并为范围的新端返回一个经过端迭代器。
通过移动(通过移动分配)范围内的元素将被删除显示在范围的开头。的相对顺序保留的元素和容器未更改。-http://en.cppreference.com/
移动赋值使移动的变量处于有效但未指定的状态,因此它可能保持不变,也可能不保持不变。
要真正从容器中删除元素,需要调用erase
。
下面是一个具体的例子:
#include <iostream>
#include <algorithm>
#include <vector>
void printVector( const std::vector<int>& v )
{
for ( auto i : v ) {
std::cout << i << ' ';
}
std::cout << std::endl;
}
int main()
{
std::vector<int> v { 0, 1, 2, 1, 3, 4 };
printVector( v ); // Prints 0 1 2 1 3 4
// Shift elemnts that aren't to be removed to the beginning of container
const auto newEnd = std::remove( v.begin(), v.end(), 1 );
printVector( v ); // Prints 0 2 3 4 * *
// Erase the unwanted elements
v.erase( newEnd, v.end() );
printVector( v ); // Prints 0 2 3 4
return 0;
}
实例
std::remove
(和std::remove_if
)是一种通用算法,也可以应用于数组。阵列的元素无法擦除。阵列的大小是固定的。您只能将数组中"已擦除"的元素移动到其尾部。数组没有方法。只能将常规函数与数组一起使用。
用户定义(即标准)容器的方法erase
确实会擦除容器的元素。此外,这种方法可以无条件地擦除元素。
考虑到要从容器中删除元素,您需要了解容器的实现细节。这就解释了为什么擦除被定义为容器的一种方法。
标准算法std::remove
和std::remove_if
实现了移动"擦除"元素的通用算法。他们不需要知道应用到的容器的实现细节。
除了方法擦除类std::list
和std::forward_list
还具有它们自己的方法remove
和remove_if
,其与一般算法std::remove
和std::remove_if
相反,根据一些条件从列表中擦除元素(类似于标准算法std::remove
和std::remove_if
)。
考虑下面的例子,看看通用算法std::remove
和类std::list
的方法remove
之间的区别
#include <iostream>
#include <algorithm>
#include <list>
int main()
{
std::list<int> l = { 1, 10, 2, 3, 10, 4 };
std::cout << "size of the list is " << l.size() << std::endl;
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
std::remove( l.begin(), l.end(), 10 );
std::cout << "nsize of the list is " << l.size() << std::endl;
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
l = { 1, 10, 2, 3, 10, 4 };
l.remove( 10 );
std::cout << "nsize of the list is " << l.size() << std::endl;
for ( int x : l ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
程序输出为
size of the list is 6
1 10 2 3 10 4
size of the list is 6
1 2 3 4 10 4
size of the list is 4
1 2 3 4