GCC 中的 std::string 实现及其短字符串的内存开销

问题描述 投票:0回答:3
我目前正在开发一个低内存平台的应用程序,该平台需要一个包含许多短字符串的 std::set(>100,000 个字符串,每个字符串包含 4-16 个字符)。我最近将这个集合从 std::string 转换为 const char * 以节省内存,我想知道我是否真的避免了每个字符串的所有开销。

我尝试使用以下内容:

std::string sizeTest = "testString"; std::cout << sizeof(sizeTest) << " bytes";
但它只给了我 4 个字节的输出,表明该字符串包含一个指针。我很清楚字符串在内部将其数据存储在 char * 中,但我认为字符串类会有额外的开销。

std::string 的 GCC 实现是否会比 sizeof(std::string) 所指示的开销更多?更重要的是,对于这么大的数据集来说,它是否重要?

以下是我的平台上相关类型的大小(它是 32 位,每个字节有 8 位):

字符:1字节

无效*:4字节
字符*:4字节
std::string: 4 字节

c++ string gcc memory-management
3个回答
16
投票
嗯,至少对于 GCC 4.4.5,这是我在这方面很方便的 机器,

std::string

std::basic_string<char>
 的类型定义,并且
basic_string
 定义于
/usr/include/c++/4.4.5/bits/basic_string.h
。有很多
该文件中的间接,但归根结底是非空
std::string
存储指向其中之一的指针:

struct _Rep_base { size_type _M_length; size_type _M_capacity; _Atomic_word _M_refcount; };
内存中紧随其后的是实际的字符串数据。所以 

std::string

 是
每个字符串至少有三个单词的开销,加上
具有比 
capacity
 更高的 
`length
 的任何开销(可能
不,取决于你如何构造你的字符串——你可以检查
询问 
capacity()
 方法)。

内存分配器也会产生开销 大量小额拨款;我不知道 GCC 对 C++ 使用什么,但是 假设它与 C 中使用的

dlmalloc

 分配器类似,
每个分配至少可以有两个字,加上一些对齐空间
大小至少为 8 字节的倍数。


9
投票
我猜测您使用的是 32 位、每字节 8 位的平台。 我还将猜测,至少在您使用的 gcc 版本上,他们正在使用 std::string 的引用计数实现。 您看到的 4 字节大小是一个指向包含引用计数和字符串数据(以及任何分配器状态,如果适用)的结构的指针。

在 gcc 的设计中,唯一的“短”字符串的大小 == 0,在这种情况下,它可以与其他所有空字符串共享表示形式。 否则你会得到一个重新计数的 COW 字符串。

要亲自研究这个问题,请编写一个分配器来跟踪它分配和释放的内存量以及次数。 使用此分配器来调查您感兴趣的容器的实现。


3
投票
如果保证“100,000 个每个 4-16 个字符的字符串”,则不要使用 std::string。相反,编写您自己的 ShortString 类。有趣的是“sizeof(std::string) == 4”,这怎么可能呢? sizeof(char) 和 sizeof(void *) 是什么?

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.