在我脑干的某个地方,一个声音低语:
在C ++中,数组不需要比需要的元素数更多的内存。
std::string str = "aabbcc";
std::array<std::string, 3> str_array = {"aa", "bb", "cc"};
因此,两者应该具有相同的大小,因为(与Java不同),没有单独的大小字段或类似字段。但我还没有找到参考。
这是真的?在哪种情况下不是?
在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)
加上每个分配的字符串。
用任何语言存储字符串比你想象的要复杂得多。 C ++ std::string
必须为您提供内容的连续存储。除此之外,std::string
可以容纳更多的东西,比如指针/迭代器到最后一个字符,其中的字符数等等.std::string::size
必须是O(1),因此它必须存储的信息不仅仅是缓冲区。此外,大多数标准库实现提供SSO(小字符串优化)。启用SSO后,std::string
会分配一个小缓冲区,以避免不必要的动态分配。您还可以保留比您需要的更多内存。可以说,你需要循环收集800-1000个字符。你可以这样做:
std::string str;
for(...)
str += some_character;
但这会导致不必要的内存分配和解除分配。如果你可以估计你想要存储的字符数,你应该qazxsw poi记忆。
reserve
然后,你总是可以std::string str;
str.reserve(1000);
for(...)
str.push_back(some_character);
,以节省内存:
shrink_to_fit
您还必须注意其他事项:
str.shrink_to_fit();
增加容量,但reserve
保持不变。这意味着,size
还必须存储(或能够计算)缓冲容量允许的字符数。std::string
必须返回null终止的字符数组,所以std::basic_string::c_str
也可能包含null终止符(不幸的是我不确定它是如何完成的)因此,两者应具有相同的大小(例如6个字节),
不是正确的扣除。
std::string
使用的内存(如果要调用其大小)至少包含一个指针和分配用于保存数据的内存。
分配用于保存数据的存储器还可以包括保持终止空字符所需的空间。
特定
std::string
几乎每个字符串都可以包含以下信息:
此外,它还可能包含:
它们的大小不同。字符串以null结尾保存,为每个字符串提供额外的字节。