Почему std::string::max_size не является константой времени компиляции?

std::string предоставляет метод max_size() для определения максимального количества элементов, которые он может содержать.

Однако, чтобы вычислить максимальную длину строки в целом, программист должен создать строковый объект (возможно, пустой).

Если этому классу не нужна никакая информация от программиста, почему max_size() недоступна как константа времени компиляции? Есть ли какая-то информация о времени выполнения, необходимая для определения максимального размера строки?


person slaphappy    schedule 30.10.2012    source источник
comment
Ваша логика необходимости создания пустой строки не работает (поскольку базовый распределитель содержит эту информацию). Также max_size() не является постоянным значением. Это наибольшее значение, которое может быть выделено в настоящее время (которое зависит от состояния распределителя во время выполнения).   -  person Martin York    schedule 30.10.2012
comment
@Loki: Можете ли вы дать ссылку на свое заявление? Я спрашиваю, потому что уверен, что вы ошибаетесь (для max_size применительно к строкам; распределители — это отдельная история).   -  person Nemo    schedule 31.10.2012
comment
@Nemo: в стандарте нет ничего, что говорило бы, что это константа. Однако в некоторых реализациях он может быть постоянным. (Здесь я предполагаю -›) Если бы комитет по стандартизации хотел, чтобы это была константа, они сделали бы ее константной переменной-членом, такой как std::string::npos, но чтобы обеспечить больше возможностей для гибкости, это метод.   -  person Martin York    schedule 31.10.2012
comment
@LokiAstari: Если бы комитет по стандартам хотел этого ... они бы сделали ... Я думаю, вас не было рядом, когда они забыли объявить память std::vector непрерывной. А как насчет спецификаций исключений? Они не боги, они совершают ошибки. Стандарт C++03 говорит только (23.1) size() о максимально возможном контейнере и о том, что он должен иметь O(1). Это довольно расплывчато, IYAM, и оставляет много места для предположений относительно того, для чего это было предназначено.   -  person sbi    schedule 02.11.2012


Ответы (4)


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

См. отчет о дефектах библиотеки № 197:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3440.html#197

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

person Bo Persson    schedule 30.10.2012
comment
+1. Действительно бесполезная функция. std::string::max_size() возвращает следующее: это максимальная длина строки, которую она могла бы удержать, если бы было достаточно памяти. Удивлен, что здесь так много неправильных ответов. - person Maxim Egorushkin; 30.10.2012

std::string::max_size() звонит std::allocator::max_size() под капотом.

Согласно стандарту 20.9.6.1.10:

size_type max_size() const noexcept;

Возвращает: наибольшее значение N, для которого вызов allocate(N,0) может быть успешным.

(См. также: allocator::max_size)

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

person slaphappy    schedule 30.10.2012
comment
Стандарт не требует, чтобы строка max_size вызывала max_size распределителя. Описание стандарта для string относится к требованиям к контейнеру в разделе 23.1, в котором max_size определяется как size() максимально возможного контейнера. Это вообще не относится к распределителям, поэтому этот ответ просто неверен. - person Nemo; 31.10.2012

Вызов max_size() делегируется распределителю, используемому для контейнера.

Теоретически очень умный распределитель может вычислить max_size во время выполнения, например. в зависимости от доступной оперативной памяти.

person Andrey    schedule 30.10.2012
comment
Нет, согласно стандарту, он не делегируется распределителю. Возможно, это в вашей конкретной реализации, но это не имеет значения. Процитируйте, где в спецификации говорится что-либо о контейнере, делегирующем этот вызов своему распределителю, и я уберу свой отрицательный голос. - person Nemo; 31.10.2012
comment
@Nemo: Да, string::max_size() не требуется по стандарту. Я говорил о возможной реализации. - person Andrey; 31.10.2012

Это также должно работать:

enum : std::string::size_type {
    npos     = std::string::size_type(-1),
    max_size = npos - 1
};
person StackedCrooked    schedule 30.10.2012
comment
То, что вы подразумеваете, уже существует как std::string::npos, что не совпадает с max_size. - person leetNightshade; 31.10.2012
comment
Кроме того, max_size на x86 приведет не более чем к size_type(-2), поскольку size_type(-1) считается недопустимым размером (npos). - person leetNightshade; 31.10.2012
comment
@leetNightshade Действительно. Починил это. - person StackedCrooked; 01.11.2012