假设我有一个长序列的无序元素S s1, s2, s3,....
,它是一个任意但固定的数据类型,我希望根据一些布尔标准迭代并删除某些元素。
现在,如果我在 对序列的最终排序感兴趣之后迭代序列,那么我可以用两种方式存储我的序列
std::list
来表示序列。使用std :: list方法执行删除。 std::vector
表示序列。如果某个元素未通过该标准并且必须删除,则将其与最后一个向量元素交换并执行pop_back
。 我的问题是
1.以时间和/或记忆方式存储我的序列会更好/更有效吗?
2.如果我不得不猜测,那么我会说列表,因为如果si
的数据类型内存大小很大,交换将是昂贵的。这种推理是否正确?
答案 0 :(得分:5)
在实践中,std::vector
由于其紧密的内存位置而具有优于其他容器的强大性能优势。如果您的元素还可以移动(即交换成本低廉),那么您的第二个选项应该是您的第一个选择。使用标准的删除/擦除成语来实现它:
v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end());
您还应该设置第二个版本std::list
并比较效果:
l.remove_if(predicate);
该列表避免移动任何元素,因此从理论上讲它可能是有效的,但是内存局部性的实际效果无法被语言标准捕获,您无法绕过测量和比较实际性能。
(据说,如果您的元素类型很大,如sizeof(T) > 10000
,列表可能会比矢量更快。测试和比较,并保持您的代码模块化,以便以后更改它很容易。)< / p>
答案 1 :(得分:2)
如果你有一个C ++ 11编译器,或至少有一个rvalue引用识别器,如果你的数据类型不是平的话,那么使用swap将不需要任何费用(即,包含指向外部资源的指针,或者换句话说,是昂贵的复制)因为它只会移动你的结构。因此,如果您有这样的编译器,请为数据类型创建一个移动构造函数(对此进行读取),然后进行设置。只需使用std::vector
即可。
现在,如果你的结构是扁平的(没有外部资源)并且很大,你可能真的想使用std::list
,因为与数据类型的大小相比,内存开销会相当小。由于您似乎只对元素的双向/顺序访问感兴趣,因此这可能是使用列表的正确位置。
最后一点,也是一个重要因素,衡量。要覆盖的默认容器应始终为std::vector
。在盲目决定之前测量两者的表现。另一个重要因素是,如果您确实需要对容器执行任何其他操作,例如随机访问或此类内容。
修改:在我忘记之前,您可能还想在容纳数据的容器上创建一个视图,这可能非常便宜。
答案 2 :(得分:0)
我们只能猜测。我会说,如果对象很容易复制(例如基本类型),那么std::vector
将更有效,因为移除元素不会分配/重新分配/释放任何内存。但是如果复制元素的成本很高,那么std::list
会更好。
但是请注意,使用C ++ 11,副本将转换为移动,因此您应该考虑移动成本,这可能比副本少得多。
答案 3 :(得分:0)
在几乎所有实际情况中,最初都使用std::vector
。与往常一样,首先编写代码,然后在需要时进行优化。如果您的探查器指出vector
效率低下是原因,那么请尝试列表。我几乎从未见过它的性能优势。