【问题标题】:small string optimization for vector?向量的小字符串优化?
【发布时间】:2011-01-11 19:20:41
【问题描述】:

我知道几个(全部?)STL 实现实现了“小字符串”优化,而不是存储通常的 3 个用于开始、结束和容量的指针,如果 sizeof (字符)

我正在考虑通过简单地将向量强制转换为字符串来滚动我自己,即为字符串提供向量接口。好主意?

【问题讨论】:

  • 你的问题不是很清楚。此外,vectorstring 的接口是什么意思?您是在谈论一个特殊的 svector 类来保存小字符串吗?
  • 没有。我的意思是一个包含任意值而不是 char 类型的字符串——就像一个向量。字符串的向量接口意味着包装字符串对象并暴露向量兼容接口,添加缺少的函数,如 push_back。
  • 难道不能用分配器做点什么吗?您甚至不会获得 3 个指针的内存,因为向量还需要一种方法来知道它是处于“小”还是“大”模式。
  • 执行您所指的“空间优化”的唯一标准库实现是 Dinkumware 的标准库,它是 Microsoft 的 Visual Studio 附带的库。
  • 我从来没有尝试过,但是如果template<class T> using small_vector = std::basic_string<T>; 可以得到非常接近小型向量优化的东西吗? (它应该至少适用于 pod 类)。

标签: c++ string stl vector


【解决方案1】:

Boost 1.58 刚刚发布,它的 Container 库有一个基于 LLVM SmallVectorsmall_vector 类。

还有一个static_vector 不能超过最初给定的大小。两个容器都是仅标头。

facebook 的 folly 库也有一些很棒的容器。

它有一个small_vector,可以使用模板参数进行配置,以充当boost 的staticsmall 向量。它也可以配置为使用小整数类型进行内部大小记账,鉴于它们是 facebook,这不足为奇:)

使库跨平台的工作正在进行中,因此 Windows/MSVC 支持应该会在某一天实现...

【讨论】:

    【解决方案2】:

    您可以从 LLVM 借用 SmallVector 实现。 (仅标头,位于 LLVM\include\llvm\ADT)

    【讨论】:

    【解决方案3】:

    如果 T 是 POD 类型,为什么不用 basic_string 而不是 vector??

    【讨论】:

    • 请注意,您必须为 POD 类型编写 std::char_traits 特化(或等效的特征类)。除了需要指定一个特殊的eof 值之外,要求并没有那么严格,但我认为这有点乏味。
    • 此外,不能保证basic_string<MyPodType> 会使用小字符串优化,也没有可移植的方式来指定元素的数量,即使这样做也是如此。
    • 为什么建议误用字符串?
    【解决方案4】:

    这是几年前的discussed(该线程中的一些名称可能看起来有点熟悉:-)),但我不知道现有的实现。我不认为我会尝试使std::string 适应这项任务。对std::basic_string 的类型的确切要求没有很好地说明,但标准非常清楚,它只适用于类似于char 的东西。对于本质上不同的类型,它可能仍然有效,但很难说会发生什么——它从来没有打算用于,并且可能没有用除小整数以外的许多类型进行测试。

    完全符合std::vector 的实现需要大量工作。但是从头开始实现std::vector 的一个可用子集(甚至包括一个小的向量优化)通常不会非常困难。如果你包含一个小的向量优化,我有理由确定你不能满足std::vector 的所有要求。

    特别是,交换或移动向量对象中存储实际数据的向量意味着您需要交换/移动实际数据项,其中std::vector 的要求取决于其仅存储一个指针到数据,因此它通常可以1通过操作指针来交换或移动内容,而根本不需要实际接触数据项本身。因此,即使操作数据项本身会/将抛出,也需要能够在不抛出的情况下做这些事情。因此,小的向量优化将无法满足这些要求。

    另一方面,如上所述,对std::string 的一个要求是它只能存储可以操纵而不投掷的物品。因此,如果std::string 是一个可行的选择,那么实现您自己的vector 类似容器可能也不需要过多担心这些细节。


    1. 在一种情况下,您最终不得不交换/移动实际数据项,即使在实际 std::vector 中也是如此:如果两个向量使用不同的分配器,那么您必须通过该分配器为目标中的对象分配空间向量的分配器。

    【讨论】:

    • 从头开始正确实现std::vector非常困难。当然,如果您选择忽略异常安全,它会变得容易得多,但它不再是一个有意义(或有用)的vector 实现。
    • 感谢您的指点 - 不幸的是,讨论从未真正得出结论。我同意,实现我自己的向量不会那么困难。但是,我希望只是插入一些现成的类并查看对内存消耗的影响。我目前正在尝试各种减少内存占用的想法,这只是其中之一。
    • 话虽如此,我确实认为自定义矢量实现将是实现这一目标的最佳方式。包装现有的矢量类将很难有效地利用对象的大小,而且自定义矢量不是火箭科学,只要您小心并知道自己在做什么。
    • @jalf:这确实不是微不足道的——而且有一个要求可能无法得到满足。交换两个向量不允许抛出异常,除非分配器的复制 ctor 抛出,即使 T(T const&) 和/或 swap(T, T) 抛出。我看不出有任何方法可以使用内置缓冲区来满足该要求。
    • @Jerry: 没错,我认为这也做不到。但至少这是一个极端的情况,你可能可以在没有 nothrow 保证的情况下生活。
    猜你喜欢
    • 2018-07-27
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    相关资源
    最近更新 更多