std::string::reserve и конец строки 0

При предварительном распределении с использованием std::string::reserve Должен ли я добавить один для прекращения 0 явно во избежание перераспределения и последующего копирования?

Например, зная, что строка "Hello" длиной 5 будет храниться в std::string strДолжен ли я позвонить str.reserve(6)?

Если я правильно прочитал стандарт, то я думаю, что ответ должен быть да. За reserve это говорит

После резерва (), емкость () больше или равна аргументу резерва.

и для capacity в свою очередь это заявляет

Возвращает: Размер выделенного хранилища в строке.

Однако я не знаком с тонкостями формулировок в стандарте, и я хотел подтвердить свое подозрение.

2 ответа

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 там, чтобы покрыть завершающий символ.

Затем он продолжает "регулировать" размер, чтобы сделать его более оптимальным, используя несколько угаданных констант для minimum allocation а также page_size, но это всегда будет как минимум __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; }

Другими словами, просто возвращает указатель на актуальную строку.

Returns: The size of the allocated storage in the string.

Выделенное хранилище в строке этого оператора означает, что строка должна помещаться в выделенном пространстве. "Строка" означает "группу символов с нулем в конце", поэтому также следует включить ноль.

Другие вопросы по тегам