2009-10-20 2 views
5

Недавно я заметил, что следующая инструкция неверна с учетом std::string s.Почему не std :: string :: max_size() == std :: string :: allocator :: max_size()

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

Я нахожу это интересным, по умолчанию будет использовать std::stringstd::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, так почему бы не попробовать?

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

+0

«И если. распределение будет коротким, оно просто выбросит std :: bad_alloc, так почему бы не попробовать? »Я могу ответить на это за вас. Людям, возможно, потребуется обработать большие строки и разделить их на большие строковые фрагменты, и если они не могут фактически зависеть от того, что ему сообщает max_size, им придется прибегать к специальным ограничениям. – GManNickG

+0

Я вижу вашу точку зрения, но я не согласен. Реальность такова, что вам всегда приходится предполагать, что любой размер строки <= 'max_size()' имеет возможность сбоя, потому что он зависит от внешней переменной (сколько доступно в куче). –

+0

Согласовано. Мой единственный момент - они должны хотя бы попытаться быть точными, а не просто дать большое количество и надеяться на лучшее. Дайте практический номер надежда на лучшее. :) Жесткий вопрос. – GManNickG

ответ

10

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

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

Дополнительно here вы можете найти Core Issue # 197. Комитет рассмотрел просьбу об улучшении формулировки Стандарта, но он был отклонен.

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

4

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

Также, похоже, это касается контейнеров STL. А ведь std::basic_string - это контейнер.

+0

За исключением того, что никто, вероятно, не реализует его таким образом, следующий стандарт может не позволить ему (не совсем уверен), и ОП видит, что он значительно меньше, чем то, что позволяет распределитель. – UncleBens

1

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^