为什么"std::string::reserve()"不保留我指定的确切空间量?



std::string::reserve()没有分配我作为参数传递的确切空间量。例如,如果我试图为100个字符保留空间,它将为111个字符保留。如果我通过200,它将保留207。650为655,1000为1007。

这背后的原因是什么?

程序代码:

std::string mystr;
std::cout << "After creation   :" << mystr.capacity() << std::endl;
mystr.reserve(1000);
std::cout << "After reserve()  :" << mystr.capacity() << std::endl;
mystr = "asd";
std::cout << "After assignment :" << mystr.capacity() << std::endl;
mystr.clear();
std::cout << "After clear()    :" << mystr.capacity() << std::endl;

代码输出:

After creation   :15
After reserve()  :1007
After assignment :1007
After clear()    :1007

(IDE:Visual Studio 2012)

标准允许

C++标准允许实现保留比请求更多的内存。在标准(N3690,§21.4.4)中,规定了

void reserve(size_type res_arg=0);

成员函数reserve()是向basic_string对象通知计划的大小更改的指令,以便它可以相应地管理存储分配。

效果:reserve()之后,capacity()大于或等于reserve的自变量。[注意:使用小于capacity()res_arg参数调用reserve()实际上是非绑定收缩请求。使用res_arg <= size()的调用实际上是非约束收缩以适应请求。--结束注释]

原因:16字节边界对齐

保留的大小似乎总是一个16的倍数减去一个字符的数字,用于null终止。在x86机器上,堆上保留的内存总是自动对齐16字节。因此,对于存储器分配,四舍五入到16的次大倍数是没有成本的。

Microsoft针对malloc()的文档指出:

返回值所指向的存储空间保证适当对齐,以存储任何类型的对象。

SIMD类型的对象必须对齐16字节才能发挥最佳作用。这些是封装类型的4个浮点或2个双(或其他),适合x86机器的128位寄存器。如果数据没有正确对齐,那么加载和存储到这些内存位置可能会导致性能的巨大损失,甚至崩溃。这就是malloc()这样做的原因。因此得出了16字节对齐的结论。大多数内存分配(包括operator new)最终调用malloc()。不分配16字节的倍数只会浪费内存,否则这些内存无论如何都不会被使用。

标准不要求它准确地保留您指定的,只要求至少保留您指定的:

21.4.4基本容量

12/效果:在reserve()之后,capacity()大于或等于保留的论点。[注意:使用res_arg参数调用reserve()小于capacity()实际上是一个非绑定收缩请求。一个电话带有res_arg<=size()实际上是一个非绑定收缩以适应请求--尾注]

我必须查看源代码才能100%确定,但底层代码似乎保留了您请求的数量,并将其填充到下一个16字节边界(留下1表示null终止)这只是一个基于行为的理论。

相关内容

  • 没有找到相关文章

最新更新