当使用 std::string::reserve
进行预分配时,我是否必须明确地为终止 0
添加 one 以便避免重新分配和后续复制?
例如,知道长度为5的字符串"Hello"
将存储在std::string str
中,我是否必须调用str.string?保留(6)
?
如果我正确阅读了标准,那么我认为答案应该是是。对于 reserve
它说
After reserve(), capacity() is greater or equal to the argument of reserve.
对于 capacity
依次声明
Returns: The size of the allocated storage in the string.
不过,我不太熟悉标准中公式的微妙之处,我想证实我的怀疑。
最佳答案
C++11 确实指定(或者我在几个地方读过,实际上在 n3337 文档中找不到那个措辞?)std::string
应该存储在这样 C 风格字符串的零终止不需要重新分配。
当然,这就是 GNU C++ 库中发生的事情,在函数 _S_create 中:
template<typename _CharT, typename _Traits, typename _Alloc>
typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
basic_string<_CharT, _Traits, _Alloc>::_Rep::
_S_create(size_type __capacity, size_type __old_capacity,
const _Alloc& __alloc)
....
// NB: Need an array of char_type[__capacity], plus a terminating
// null char_type() element, plus enough for the _Rep data structure.
// Whew. Seemingly so needy, yet so elemental.
size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
+ 1
用于覆盖终止符。
然后它继续“调整”大小以使其更优化,使用一些猜测的最小分配
和page_size
常量,但它始终是 AT最小 __size
,并且总是添加 1
为终止腾出空间。
要弄清楚它“总是”这样做,您必须遵循代码并发现每当需要重新分配字符串时都会调用 _M_clone
,并且 _M_clone
依次调用 _S_create
。代码不容易阅读,因为它是为了遵循标准和高效而编写的,而不是为了让我们这些普通人阅读它。
这里更容易看出 c_str
没有分配任何东西:
const _CharT*
c_str() const _GLIBCXX_NOEXCEPT
{ return _M_data(); }
然后调用:
_CharT*
_M_data() const _GLIBCXX_NOEXCEPT
{ return _M_dataplus._M_p; }
换句话说,只是返回指向实际字符串的指针。
关于c++ - std::string::reserve 和字符串结尾 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30111288/