在我脑干的某个地方,一个声音低语:
在C ++中,数组不需要比元素数量更多的内存 需要。
std::string str = "aabbcc";
std::array<std::string, 3> str_array = {"aa", "bb", "cc"};
因此,两者应该具有相同的大小,因为(与Java不同),没有单独的 size 字段或类似字段。但我还没有找到参考。
这是真的吗?在哪种情况下不是?
答案 0 :(得分:4)
以任何语言存储字符串比您想象的更复杂。 C ++ std::string
必须为内容提供连续的存储空间。除此之外,std::string
可以容纳更多的东西,比如指针/迭代器到最后一个字符,其中的字符数等等。std::string::size
必须是O(1),所以它必须存储更多信息而不仅仅是缓冲区。此外,大多数标准库实现提供SSO(小字符串优化)。启用SSO后,std::string
会分配一个小缓冲区,以避免不必要的动态分配。您还可以保留比您需要的更多内存。可以说,你需要循环收集800-1000个字符。你可以这样做:
std::string str;
for(...)
str += some_character;
但这会导致不必要的内存分配和解除分配。如果您可以估算要存储的字符数,则应该reserve
内存。
std::string str;
str.reserve(1000);
for(...)
str.push_back(some_character);
然后,你总是shrink_to_fit
,以节省内存:
str.shrink_to_fit();
您还必须注意其他事项:
reserve
会增加容量,但size
保持不变。这意味着,std::string
还必须存储(或能够计算)缓冲容量允许的字符数。std::basic_string::c_str
必须返回以null结尾的字符数组,因此std::string
也可能包含空终止符(不幸的是我不确定它是如何完成的)答案 1 :(得分:2)
在C ++中,数组不需要比需要的元素数量更多的内存。
这是事实。原始数组的大小等于它的大小,元素类型乘以元素数。所以
int array[10];
的大小为sizeof(int) * std::size(array)
。 std::array
是相同的,但允许填充
std::array<int, 10> array;
的大小为sizeof(int) * std::size(array) + P
,其中P
是一些整数填充量。
你的例子虽然不是一回事。 std::string
是一个容器。它有自己的大小,它与它所包含的内容是分开的。因此,无论字符串中有多少个字符,sizeof(std::string)
始终都是一样的。所以忽略短字符串优化
std::string str = "aabbcc";
取sizeof(std::string)
加上为底层c字符串分配的字符串。这与
std::array<std::string, 3> str_array = {"aa", "bb", "cc"};
由于您现在拥有3 * sizeof(std::string)
以及分配的每个字符串。
答案 2 :(得分:1)
因此,两者应具有相同的大小(例如6个字节),
不是正确的扣除。
std::string
使用的内存(如果要调用其大小)至少包含一个指针和分配用于保存数据的内存。
分配用于保存数据的内存还可以包含保存终止空字符所需的空间。
鉴于
std::string s = "aabbcc";
std::string a = "aa";
std::string b = "bb";
std::string c = "cc";
mem(s) != mem(a) + mem(b) + mem(c)
答案 3 :(得分:1)
几乎每个字符串都可以包含以下信息:
字符串的大小,即它包含的字符数。
持有字符串字符的内存容量。
字符串的值。
另外它也可能有:
答案 4 :(得分:-3)
它们的大小不同。字符串以null结尾保存,为每个字符串提供额外的字节。