std :: string :: reserve和end-of-string 0

Xle*_*lea 6 c++ stdstring dynamic-memory-allocation

当使用pre预分配时std::string::reserve,我必须明确添加一个用于终止0,以避免重新分配和后续复制?

例如,知道"Hello"长度为5 的字符串将被存储std::string str,我是否必须调用str.reserve(6)

如果我正确地阅读了标准,那么我认为答案应该是肯定的.因为reserve它说

在reserve()之后,capacity()大于或等于reserve的参数.

capacity反过来它规定

返回:字符串中已分配存储的大小.

不过,我不熟悉标准中配方的细微之处,我想证实我的怀疑.

Mat*_*son 8

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

+ 1有覆盖终止字符。

然后它继续“调整”大小以使其更优化,使用一些猜测的常量minimum allocationpage_size,但它总是至少__size,并且总是增加1为终止腾出空间。

要弄清楚它“总是”这样做,您必须遵循代码并发现_M_clone每当需要重新分配字符串时都会_M_clone调用,然后调用_S_create. 代码不易阅读,因为它的编写是为了遵循标准和高效,而不是为了让我们凡人阅读它。

更容易看到c_str不分配任何东西在这里:

  const _CharT*
  c_str() const _GLIBCXX_NOEXCEPT
  { return _M_data(); }
Run Code Online (Sandbox Code Playgroud)

然后调用:

  _CharT*
  _M_data() const _GLIBCXX_NOEXCEPT
  { return  _M_dataplus._M_p; }
Run Code Online (Sandbox Code Playgroud)

换句话说,只返回指向实际字符串的指针。


小智 2

Returns: The size of the allocated storage in the string.
Run Code Online (Sandbox Code Playgroud)

字符串中的分配存储 该语句意味着字符串应该适合分配的空间。“字符串”的意思是“以零结尾的字符组”,因此也应该包括零。

  • @Tomasz Pluta:当然,实现可以选择实际上使容量更大;但*是*允许它相等的。在后一种情况下,根据分配空间的计数(见上文),可能需要重新分配才能将 0 存储在某处;“Hello”已经占用了所有预先分配的 5 个字符存储空间。 (2认同)