Почему не std::string::max_size() == std::string::распределитель::max_size()

StackOverflow https://stackoverflow.com/questions/1592476

  •  22-09-2019
  •  | 
  •  

Вопрос

Недавно я заметил, что следующее утверждение неверно, учитывая std::string s.

s.max_size() == s.get_allocator().max_size();

Я нахожу это интересным по умолчанию std::string будет использовать std::allocator<char> который имеет теоретический предел в size_type(-1) (да, я знаю, что предполагаю дополнение 2, но это не имеет отношения к самому вопросу).Я знаю, что практические ограничения будут значительно меньше этих.В типичной 32-разрядной системе x86 ядро будет занимать 2 ГБ (возможно, 1 ГБ) адресного пространства, оставляя гораздо меньший практический верхний предел.

Во всяком случае, GNU libstdc++ std::basic_string<>::max_size() кажется, возвращает одно и то же значение независимо от того, что говорит используемый распределитель (что-то вроде 1073741820).

Таким образом, остается вопрос, почему этого не происходит std::basic_string<>::max_size() просто вернись get_allocator().max_size()?Мне кажется, что это гипотетический верхний предел.И если выделение окажется недостаточным, это просто выбросит std::bad_alloc, так почему бы не попробовать?

Это скорее любопытство, чем что-либо еще, мне просто интересно, почему эти два понятия определены отдельно, по крайней мере, в этой реализации.

Это было полезно?

Решение

В Microsoft Connect была опубликована ошибка, связанная с вашим вопросом.У Microsoft есть интересный ответ на этот вопрос:

Мы решили это как Задуманное в соответствии с нашей интерпретацией Стандарта, которая четко не объясняет, какова предполагаемая цель max_size().Распределитель max_size() описывается как "наибольшее значение, которое может быть осмысленно передано в X::allocate()" (C ++ 03 20.1.5 [lib.allocator.requirements]/Таблица 32), но контейнер max_size() описывается как "размер () максимально возможного контейнера" (23.1 [lib.container.requirements]/Таблица 65).Ничто не описывает, должен ли контейнер max_size() быть производным от распределителя max_size() и каким образом.Наша реализация в течение многих лет производила container max_size() непосредственно из распределителя max_size(), а затем использовала это значение для проверки переполнения и так далее.Другие интерпретации Стандарта, такие как ваша, возможны, но не являются для нас однозначно правильными.Здесь, безусловно, было бы полезно уточнить формулировку Стандарта.До тех пор, пока этого не произойдет, мы решили оставить нашу текущую реализацию без изменений по двум причинам:(1) другие клиенты могут зависеть от нашего текущего поведения, и (2) max_size() принципиально ничего не покупает.Самое большее, что использует распределители (например, контейнеры), может использовать распределитель max_size() для прогнозирования сбоя функции allocate(), но простой вызов allocate() является лучшим тестом, поскольку распределитель затем решит, выделять память или нет.Вещи, которые используют контейнеры, могут использовать container max_size() в качестве гарантии того, насколько большим может быть size(), но более простой гарантией является диапазон size_type .

Дополнительно здесь вы могли бы найти Основную проблему № 197.Комитет рассмотрел просьбу улучшить формулировку Стандарта, но она была отклонена.

Итак, ответ на ваш вопрос "Почему ..?" заключается в том, что Стандарт четко не объясняет, какова предполагаемая цель max_size().

Другие советы

Я не совсем уверен, но насколько я знаю std::basic_string В текущем стандарте не ограничено хранение строки в постоянной памяти.Например, он может хранить его в нескольких фрагментах.Каждый такой фрагмент затем ограничивается std::allocator::max_size() но сумма может быть больше.

Похоже, то же самое относится и к контейнерам STL.И в конце концов std::basic_string является контейнером.

Реализация GCC имеет комментарий о том, как они рассчитывают. max_size (необходимо вычесть размер внутреннего служебного объекта, который выделяется как один блок со строкой), а затем добавить это max_size() возвращает четверть этой суммы.Обоснования нет, так что, возможно, это просто запас прочности?(Он также должен предоставить класс веревки, который, возможно, можно было бы использовать для таких больших строк?)

С ВК++ max_size() возвращает на единицу меньше allocator.max_size() - вероятно, для учета завершающего нулевого символа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top