为什么sizeof(string)== 32?

时间:2010-09-22 15:19:25

标签: c++ string

字符串结构的开销是什么导致sizeof()为32?

6 个答案:

答案 0 :(得分:45)

大多数现代std::string实现 1 在一个静态大小的char数组中直接在堆栈上保存非常小的字符串,而不是使用动态堆存储。这被称为Small (or Short) String Optimisation(SSO)。它允许实现避免小字符串对象的堆分配,并改善引用的局部性。

此外,将有std::size_t成员保存字符串大小和指向实际char存储的指针。

具体实现方式有所不同,但以下几行有效:

template <typename T>
struct basic_string {
    char* begin_;
    size_t size_;
    union {
        size_t capacity_;
        char sso_buffer[16];
    };
};

sizeof (void*) = 8的典型架构中,这给我们的总大小为32个字节。


1 “三巨头”(GCC的libstdc ++自第5版以来,Clang的libc ++和MSVC的实现)都是这样做的。其他人也可能。

答案 1 :(得分:11)

std::string通常包含“小字符串优化”的缓冲区---如果字符串小于缓冲区大小,则不需要堆分配。

答案 2 :(得分:4)

我的猜测是:

class vector
{
    char type;
    struct Heap
    {
      char*   start;
      char*   end;
      char*   allocatedEnd;
    };
    struct Stack
    {
      char    size;
      char    data[27];
    }
    union
    {
        Stack   stackVersion;
        Heap    heapVersion;
    } version;
};

但我敢打赌有数百种方法可以做到。

答案 3 :(得分:3)

它依赖于库。您不应该依赖std::string个对象的大小,因为它可能会在不同的环境中发生变化(显然在不同的标准库供应商之间,以及同一个库的不同版本之间)。

请记住std::string实现是由针对各种用例进行优化的人编写的,通常会导致2个内部表示,一个用于短字符串(小内部缓冲区),一个用于长字符串(堆) - 分配的外部缓冲区)。开销与在每个std::string对象中保存这两者相关联。

答案 4 :(得分:3)

在g ++ 5.2中(例如g ++ 4.9,它不同)字符串基本上定义为:

class string {
  char* bufferp;
  size_t length;
  union {
    char local_buffer[16];
    size_t capacity;
  };
};

在普通计算机上,这最多可增加32个字节(8 + 8 + 16)。

实际的定义当然是

typedef basic_string<char> string;

但想法是一样的。

答案 5 :(得分:1)

问:为什么狗是黄色的? 答:不一定。

(一个?)std :: string对象的大小取决于实现。我刚检查了MS VC ++ 2010.它确实对std :: string使用了32个字节。有一个16字节的联合,它包含字符串的文本,如果它适合,或者包含指向更长字符串的堆存储的指针。如果实现者选择在字符串对象中而不是在堆上保留18个字节的字符串,则大小将为34个字节。其他16个字节包含开销,包含字符串的长度和当前为字符串分配的内存量。

不同的实现可能总是从堆中分配内存。毫无疑问,这样的实现需要较少的字符串对象内存。