C ++数组的内存效率

问题描述 投票:0回答:5

在我脑干的某个地方,一个声音低语:

在C ++中,数组不需要比需要的元素数更多的内存。

std::string str = "aabbcc"; 
std::array<std::string, 3> str_array = {"aa", "bb", "cc"}; 

因此,两者应该具有相同的大小,因为(与Java不同),没有单独的大小字段或类似字段。但我还没有找到参考。

这是真的?在哪种情况下不是?

c++ arrays string size
5个回答
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)加上每个分配的字符串。


4
投票

用任何语言存储字符串比你想象的要复杂得多。 C ++ std::string必须为您提供内容的连续存储。除此之外,std::string可以容纳更多的东西,比如指针/迭代器到最后一个字符,其中的字符数等等.std::string::size必须是O(1),因此它必须存储的信息不仅仅是缓冲区。此外,大多数标准库实现提供SSO(小字符串优化)。启用S​​SO后,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还必须存储(或能够计算)缓冲容量允许的字符数。
  • 字符串文字以null结尾
  • std::string必须返回null终止的字符数组,所以std::basic_string::c_str也可能包含null终止符(不幸的是我不确定它是如何完成的)
  • 有更多的编码和字符集 - ASCII只是其中之一。 UTF-8和UTF-16编码的字符串可能需要使用少量存储元素来添加一个代码点,但这更复杂。

1
投票

因此,两者应具有相同的大小(例如6个字节),

不是正确的扣除。

std::string使用的内存(如果要调用其大小)至少包含一个指针和分配用于保存数据的内存。

分配用于保存数据的存储器还可以包括保持终止空字符所需的空间。

特定

std::string

1
投票

几乎每个字符串都可以包含以下信息:

  • 字符串的大小,即它包含的字符数。
  • 保存字符串字符的内存容量。
  • 字符串的值。

此外,它还可能包含:

  • 它的分配器和引用计数的副本。

-3
投票

它们的大小不同。字符串以null结尾保存,为每个字符串提供额外的字节。

© www.soinside.com 2019 - 2024. All rights reserved.