【问题标题】:Memory allocation for strings in vectors向量中字符串的内存分配
【发布时间】:2017-03-21 05:47:43
【问题描述】:

如果向量总是提供连续的内存存储,编译器如何为空的 std::strings 分配内存?

我有一个向量,我已将多个类推送到其中,并将 std:string 作为私有成员。然后,我将对向量的引用作为参数传递给另一个方法。

堆中其他地方的字符串数据是否引用自向量的连续数组?

【问题讨论】:

    标签: c++ c++11 vector


    【解决方案1】:

    std::string 分配内存微不足道

    在内部,它会有某种指针指向一块内存,实际的字符串数据将存储在该内存块中。因此,为 std::string 分配内存只是为指针、size_t 或其他东西分配空间,也许还有更多原语。

    例如,如果您有一个std::vector<std::string>,向量很容易为std::string 分配空间,因为它们只是k 字节,每个常量k。本次分配不涉及字符串数据。

    【讨论】:

      【解决方案2】:

      在这种情况下,内存中实际发生的事情的详细信息完全取决于您正在使用的特定 STL 实现。

      话虽如此,我的印象是,在大多数实现中,向量和字符串都是用类似(非常简化的):

      template<typename T>
      class vector
      {
        //...
        private:
          T* _data;
      };
      
      class string
      {
        private:
          char _smallStringsBuffer[kSmallSize];
          char* _bigStringsBuffer;
      };
      

      向量的数据是根据容量在堆上动态分配的(默认初始化时有一个默认值,并在向向量添加元素时增长)。

      字符串的数据是静态分配给小字符串的(“small”的实现依赖值),然后当字符串变大时动态分配。出现这种情况的原因有很多,但主要是为了更有效地处理小字符串。

      你描述的例子是这样的:

      void MyFunction(const vector<string>& myVector)
      {
        // ...
      }
      
      int main()
      {
        vector<string> v = ...;
      
        // ...
      
        MyFunction(v);
      
        // ...
      
        return 0;
      }
      

      在这种特殊情况下,只有向量 v 的基本数据将在堆栈中,因为 v._data 将在堆上分配。如果 v 的容量为 N,则 v._data 在堆中的大小将为 sizeof(string) * N,其中字符串的大小是一个常数,取决于 kSmallSize * sizeof(char) + sizeof (char*),基于上面字符串的定义。

      对于连续数据,只有当向量中收集的所有字符串的字符数都少于 kSmallSize 时,它​​们的数据才会在内存中“几乎”连续。

      这是性能关键代码的一个重要考虑因素,但老实说,我认为大多数人不会在这种情况下依赖标准 STL 的向量和字符串,因为实现细节会随着时间和不同平台而变化和编译器。此外,当您的代码超出“快速”路径时,您不会注意到,除非出现难以控制的延迟高峰。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-03-22
        • 1970-01-01
        • 2021-07-27
        • 2022-12-23
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        相关资源
        最近更新 更多