为什么Vector在列表提供时不提供remove()成员函数?

时间:2011-06-22 22:03:44

标签: c++

如果我想用vector中的值删除所有元素,我调用remove algorithm 然后调用vector的erase成员函数来物理删除它。      但是在list的情况下,简单的调用删除成员函数,它将删除具有该值的所有元素。     我不确定为什么vector在列表执行时不提供删除MF。

对于Exp:我想从vector v。

中删除值'4'
vector<int> v;
vector<int> ::iterator Itr;
for (int i=0; i< 6; i++)
   v.push_back(i*2);
v.push_back(4);
v.push_back(8);
v.push_back(4);
v.erase(remove(v.begin(),v.end(),4), v.end()); 

和列表:

list.remove(4); // will delete all the element which has value 4

5 个答案:

答案 0 :(得分:9)

问题不是为什么std::vector不提供操作,而是为什么std::list提供它。 STL的设计侧重于通过迭代器分离容器和算法,并且在迭代器方面可以有效地实现算法的所有情况下,这是可选的。

然而,在某些情况下,有一些特定的操作可以通过容器的知识更有效地实现。这是从容器中删除元素的情况。使用 remove-erase 习语的成本在容器的大小上是线性的(不能减少很多),但这隐藏了这样一个事实:在最坏的情况下,除了其中一个操作之外的所有操作都是< em> copy 对象(匹配的唯一元素是第一个),这些副本可以代表相当大的隐藏成本。

通过将操作实现为std::list中的方法,操作的复杂性仍然是线性的,但删除的每个元素的相关成本非常低,一对指针复制和释放内存中的节点。同时,作为列表一部分的实现可以提供更强的保证:未擦除元素的指针,引用和迭代器不会在操作中失效。

在特定容器中实现的算法的另一个示例是std::list::sort,它使用mergesort效率低于std::sort但不需要随机访问迭代器。

基本上,算法是用迭代器实现的自由函数,除非有充分理由在具体容器中提供特定的实现。

答案 1 :(得分:4)

我认为理由是std::list提供了一种非常有效的remove方法(如果实现为双向链接列表,它只调整指向元素的指针并释放其存储空间),同时删除元素std::vector速度相对较慢。

remove+erase技巧是适用于提供所需迭代器类型的所有容器类型的标准方法。据推测,STL的设计师想要指出这种差异。他们可以选择为所有容器提供remove方法,除了那些知道更好方法的容器外,所有容器都是remove+erase,但他们没有。

这似乎乍一看违反了通用代码的想法,但我认为它确实没有。拥有一个易于访问的简单通用remove,可以很容易地编写可以编译所有容器类型的通用代码,但最后通用代码在10个案例中的9个中运行速度非常慢,而且速度非常快第十个不是真正的泛型,它只是看起来如此。

可以在std::map::find与通用std::find找到相同的模式。

答案 2 :(得分:3)

从向量中删除元素比对列表这样做要慢得多:它(平均)与向量的大小成比例,而列表上的操作是在恒定时间内执行的。

标准库的设计者决定不将此功能包含在“看起来容易(易于计算)”的原则中。

我不确定我是否同意这一理念,但它被认为是C ++的设计目标。

答案 3 :(得分:1)

因为从列表中删除项目很便宜,而在向量上执行此操作非常昂贵 - 所有后续元素都必须移位,即复制/移动。

答案 4 :(得分:0)

我想,由于效率问题,从矢量中删除随机元素比从列表中删除更慢。对于这样的情况,这可能意味着更多的打字,但至少在界面中显而易见的是std::vector不是最好的数据结构,如果你需要经常这样做。