【问题标题】:Iterating through a sequence while modifying it. Use vector or List ? C++/ STL在修改序列时迭代它。使用向量还是列表? C++/STL
【发布时间】:2012-01-19 20:24:01
【问题描述】:

假设我有一个长序列的无序元素 S s1, s2, s3,.... 是任意但固定的数据类型,我希望通过它根据一些布尔标准迭代和删除某些元素。

现在,如果在遍历序列之后,如果我对序列的最终排序感兴趣,那么我可以以 2 种方式存储我的序列

  1. 使用普通的“std::list”来表示序列。使用 std::list 方法执行删除。
  2. 使用std::vector 来表示序列。如果某个元素不符合标准并且必须被删除,则将其与最后一个向量元素交换并执行pop_back

我的问题是

1.在时间和/或记忆方面存储我的序列的更好/有效方式是什么?

2.如果我不得不冒险猜测,那么我会说列表,因为如果si 的数据类型内存大小很大,那么交换会很昂贵。这种推理是否正确?

【问题讨论】:

  • 这个无法回答。您将不得不衡量性能。如果你能提供完整的源代码,那么我们也许可以做一些分析,但以目前的形式,这个问题无法回答。
  • std::vector + std::remove_if。我从未见过我想要std::list 的情况(我假设是因为我从不需要拼接。)

标签: c++ algorithm stl


【解决方案1】:

在实践中,std::vector 与其他容器相比具有很大的性能优势,因为它具有严格的内存局部性。如果您的元素也是可移动的(即交换成本低廉),那么您的第二个选择应该是您的第一次尝试。使用标准的 remove/erase 习惯用法实现它:

v.erase(std::remove_if(v.begin(), v.end(), predicate), v.end());

您还应该使用std::list 设置第二个版本并比较性能:

l.remove_if(predicate);

该列表避免移动任何元素,因此理论上它可能是有效的,但是语言标准无法捕捉到内存局部性的实际效果,并且您无法绕过测量和比较实际性能。

(假设,如果您的元素类型很大,例如sizeof(T) > 10000,则列表可能会开始比向量快。测试和比较,并保持您的代码模块化,以便以后轻松更改。)

【讨论】:

    【解决方案2】:

    如果你有一个 C++11 编译器,或者至少一个支持右值引用的编译器,如果你的数据类型不是扁平的(即包含指向外部资源的指针,或者换句话说,它很昂贵,那么使用交换将不会花费你任何成本)复制),因为它只会移动你的结构。因此,如果您有这样的编译器,请为数据类型创建一个移动构造函数(阅读该构造函数),然后就可以设置了。从那里开始使用std::vector

    现在,如果您的结构是扁平的(没有外部资源)并且很大,您可能真的想使用std::list,因为与您的数据类型的大小相比,内存开销会相当小。由于您似乎只对元素的双向/顺序访问感兴趣,因此这可能正是使用列表的正确位置。

    最后一点,也是一个重要因素,衡量。要访问的默认容器应始终为std::vector。在盲目地决定一个之前衡量两者的表现。另一个重要因素是你是否真的需要对容器做任何其他事情,比如随机访问或类似的东西。

    编辑:在我忘记之前,您可能还只想在保存数据的容器上创建一个视图,这可能非常便宜。

    【讨论】:

      【解决方案3】:

      我们只能猜测。我想说,如果对象很容易复制(例如基本类型),那么std::vector 会更有效,因为删除元素不会分配/重新分配/释放任何内存。但如果复制元素的成本很高,那么std::list 会更好。

      但请注意,在 C++11 中,副本将转换为移动,因此您应该考虑移动成本,这可能会比副本少很多。

      【讨论】:

        【解决方案4】:

        在几乎所有实际情况下,最初使用std::vector。与往常一样,先编写代码,然后在需要时进行优化。如果您的分析器表明vector 的效率低下是原因,请尝试列出。不过,我几乎从未见过它带来的性能优势。

        【讨论】:

          猜你喜欢
          • 2018-10-12
          • 1970-01-01
          • 1970-01-01
          • 2014-09-17
          • 2011-05-30
          • 2017-12-05
          • 2012-04-20
          • 1970-01-01
          • 2012-11-05
          相关资源
          最近更新 更多