【问题标题】:C++: mixture between vector and list: something like std::rope?C ++:向量和列表之间的混合:类似于std::rope?
【发布时间】:2011-04-15 20:36:27
【问题描述】:

当存储一堆项目并且我不需要随机访问容器时,我使用的是std::list,这基本没问题。但是,有时(尤其是当我只是将条目推回后面并且从不删除中间某处时),我希望我有一些具有更好性能的结构来添加条目。

std::vector 不好,因为:

  • 如果不再适合,则必须重新分配。
  • 它实际上不适用于大量数据(因为您不能总是获得非常大的连续可用内存块)。

std::list 不好,因为:

  • 它对每一个 push_back 进行分配。这很慢,会导致大量内存碎片。

所以,介于两者之间的东西就是我想要的。

基本上,我想要std::list< boost::array<T, 100> > 之类的东西。或者也许不是100,而是4096/sizeof(T)。也许还有std::list< std::vector<T> >,第一个向量可以很小,然后可以增长。实际上我想隐藏它的使用,所以我可以做一个mycontainer.push_back(x)

std::rope 有点类似,但标准中没有。

Boost 里面有这样的东西吗?

【问题讨论】:

  • 为什么不直接使用 SGI 发行版的rope 类?许可证中有广告条款,但除此之外,为什么不呢?
  • @Albert,你说你只是用 push_back 存储一堆项目。那么 std::vector 有什么问题呢?为什么更喜欢 std::list?
  • @ybungalobill: std::vector 不适合非常大的数据块,因为内存只是连续分配的。
  • @Matt:我希望它可以在任何地方工作(即在所有可能的 STL 实现的编译器上)。
  • @AshleysBrain:这给了我什么好处(除了在前面不断插入,我在这里不关心)?

标签: c++ arrays boost stl vector


【解决方案1】:

是的,它被称为 std::vector。这是 O(1) 时间 push_back 几乎总是比 std::list 快。 (是的,而且它也很节省内存)

std::list 最重要的特性是从中间进行恒定时间删除/插入。如果您不需要它,请选择 std::vector。

【讨论】:

  • 如果您有大量 vector 的对象复制起来很昂贵,那么在 push_back 期间偶尔发生的重新分配可能会使 vector 成为不可接受的选择。
  • 不,对于向量上的 push_back,它不是 O(1)。它开着)。平均而言,它应该类似于 O(log n)。而且它根本不适用于大量数据,因为它只能分配一大块连续内存。而且 std::list 很慢,因为它必须为每个 push_back 进行分配。
  • @Albert:不,最后的插入(即push_back 所做的)具有摊销的常数时间复杂度(O(1))。这意味着平均而言,在末尾插入一个元素需要恒定的时间。只有当需要重新分配时,最后的插入才需要线性时间。 vector 的实现使得重新分配相对不频繁发生,通常是通过使底层存储呈指数增长。
  • @Albert:不,仍然是 O(1)。考虑一个大小为 1,000 且容量为 1,000 的向量。您插入一个元素并进行重新分配,将容量增加到 2,000。这种重新分配需要 1,000 个时间单位。然后,您可以在恒定时间内再插入 999 个元素。重新分配所花费的时间(1,000 个时间单位)在下一次重新分配之前可以执行的 1 + 999 = 1,000 次插入中摊销; 1,000 / 1,000 = 1。[是的,这很简单,并非所有实现都使用 2 倍比例因子;例如,我认为 VC++ 使用 1.5x,但这是关于它的工作原理。]
  • @Albert 这是 O(1),阅读摊销分析。如果您插入 N 个对象,那么您最多总共进行 2N 次复制操作
【解决方案2】:

您是否考虑过使用std::deque?它的元素不是连续存储的,但它确实允许随机访问元素;如果您只在序列的开头或结尾插入元素,它可能比std::vector 提供更好的性能。

【讨论】:

  • 令人惊讶的是,很少有人知道 std::deque 但它确实应该是大型数据集的默认设置
  • 我真的应该更了解 STL!我一直想知道deque 的用途以及它与vector 的(内部)有何不同(我一直认为它只是一个块,当您在前面插入时,起始索引可能会改变)。
  • IIRC,MSVC 使用了非常糟糕的块大小,使其表现得像一个链表。查看 Boost.Containers 以获得跨编译器的一致实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 2011-09-14
  • 2012-10-20
  • 2020-05-12
  • 2018-02-21
  • 2018-11-14
相关资源
最近更新 更多