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

hkB*_*sai 3 c++ memory-management stl stdstring

std::string::reserve()不会分配我作为参数传递的确切空间量.例如,如果我尝试为100个字符保留空间,则保留111个字符.如果我通过200,它预留207. 655,650,1007 1000.

这背后的原因是什么?

程序代码:

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;
Run Code Online (Sandbox Code Playgroud)

代码输出:

After creation   :15
After reserve()  :1007
After assignment :1007
After clear()    :1007
Run Code Online (Sandbox Code Playgroud)

(IDE:Visual Studio 2012)

Ral*_*zky 7

该标准允许它

C++标准允许实现保留比请求更多的内存.在标准(N3690,§21.4.4)中说明

void reserve(size_type res_arg=0);
Run Code Online (Sandbox Code Playgroud)

成员函数reserve()是通知一个一个指令basic_string在尺寸有计划的变化的对象,因此,它可以相应地管理存储分配.

效果:之后reserve(),capacity()大于或等于参数reserve.[ 注意:reserve()使用res_arg小于的参数调用capacity()实际上是非绑定收缩请求.调用res_arg <= size()实际上是一个非绑定的缩小到适合请求.- 结束说明 ]

原因是:对齐16字节边界

似乎保留的大小总是一个16的倍数减去空终止的一个字符的数字.堆上保留的内存始终在x86计算机上自动进行16字节对齐.因此,对于内存分配,没有成本可以累计到16的下一个最大倍数.

微软文档malloc()指出:

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

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


Joh*_*ing 5

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

21.4.4 basic_string capacity [string.capacity]

12 /效果:在reserve()之后,capacity()大于或等于reserve的参数.[注意:使用小于capacity()的res_arg参数调用reserve()实际上是非绑定收缩请求.使用res_arg <= size()的调用实际上是一个非绑定的缩小到适合请求. - 尾注]