为什么std::whatever::erase()是一个方法,std::remove()是独立函数



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::removestd::remove_if实现了移动"擦除"元素的通用算法。他们不需要知道应用到的容器的实现细节。

除了方法擦除类std::liststd::forward_list还具有它们自己的方法removeremove_if,其与一般算法std::removestd::remove_if相反,根据一些条件从列表中擦除元素(类似于标准算法std::removestd::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 

最新更新