大多数现代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 5版起使用的libstdc++、Clang的libc++和MSVC的实现)都这样做。其他的实现也可能这样做。
--with-default-libstdcxx-abi=gcc4-compatible
配置你的GCC,但那将是一个可怕的想法(=非常旧的实现)。 - Konrad Rudolphstd::string
通常包含一个用于"小字符串优化"的缓冲区 --- 如果字符串长度小于该缓冲区大小,则不需要进行堆分配。
class string {
char* bufferp;
size_t length;
union {
char local_buffer[16];
size_t capacity;
};
};
typedef basic_string<char> string;
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;
};
但我敢打赌有数百种方法可以做到这一点。
std::string
进行引用计数的尝试,但很明显这并不是很高效(多年来有几篇论文对此进行了研究),因此短字符串优化变得流行起来。 - Martin York它依赖于库。你不应该依赖于std::string
对象的大小,因为在不同的环境中它很可能会改变(显然在不同的标准库供应商之间,但也会在相同库的不同版本之间发生变化)。
请记住,std::string
的实现是由优化了各种用例的人编写的,通常会导致2种内部表示,一种是短字符串(小内部缓冲区),一种是长字符串(堆分配的外部缓冲区)。与容纳这两个内容相关的开销都与每个std::string
对象有关。
问:为什么狗是黄色的? 答:不一定。
std::string对象的大小取决于实现。我刚刚检查了MS VC++ 2010。它确实使用32个字节来存储std::string。有一个16字节的联合体,其中包含字符串的文本(如果适合)或指向长字符串的堆存储的指针。如果实现者选择将18字节的字符串保留在字符串对象中而不是在堆上,则大小将为34字节。其他16个字节包括开销,包括字符串的长度和当前为字符串分配的内存量。
不同的实现可能总是从堆中分配内存。这样的实现无疑需要更少的内存来存储字符串对象。
<string>
头文件,你就可以准确地看到为什么std::string
的大小是那个大小。@Queso:sizeof
返回一个对象占用的字节数。 - James McNellis