Подтвердить что ты не робот

В С++ 11 и далее выполняется std::string:: operator [] проверка границ?

Я видел много раз, что std::string::operator[] не выполняет никаких ограничений. Даже В чем разница между строкой:: at и string:: operator []?, заданной в 2013 году, ответы говорят, что operator[] не выполняет никаких проверок границ.

Моя проблема в том, что если я посмотрю на стандарт (в данном случае проект N3797) в [string.access], у нас есть

const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
  • Требуется: pos <= size().
  • Возвращает: *(begin() + pos), если pos < size(). В противном случае возвращается ссылка на объект типа charT со значением charT(), где изменение объекта приводит к поведению undefined.
  • Броски: ничего.
  • Сложность: постоянное время.

Это заставляет меня думать, что operator[] должен выполнить некоторую проверку границ, чтобы определить, нужно ли возвращать элемент строки или значение по умолчанию charT. Правильно ли это предположение, и теперь требуется operator[] для проверки границ?

4b9b3361

Ответ 1

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

Он говорит следующее:

  • Предварительным условием является то, что аргумент [] равен либо n, либо он равен lt; п.
  • Предполагая, что условие выполнено:
    • Если оно < n, тогда вы получите персонажа, которого вы попросили.
    • "В противном случае" (т.е. если это n), вы получаете charT() (т.е. нулевой символ).

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

Таким образом, реализациям не нужно выполнять проверку границ и hellip; и общие не будут.

Ответ 2

operator[] выполняет некоторую проверку границ, чтобы определить...

Нет, нет. С предварительным условием

Требуется: pos <= size().

он может просто ASSUME, чтобы он всегда мог возвращать элемент строки. Если это условие не выполняется: Undefined поведение.

operator[], скорее всего, просто увеличит указатель от начала строки pos. Если строка короче, то она просто возвращает ссылку на данные за строкой, какими бы они ни были. Как классика за пределами простых C-массивов.

Чтобы заполнить случай, когда pos == size(), он мог бы просто выделить дополнительный charT в конце своих внутренних строковых данных. Таким образом, просто увеличивая указатель без каких-либо проверок, он все равно выполнит указанное поведение.

Ответ 3

Во-первых, существует условие require. Если вы нарушаете условие require, ваша программа ведет себя как undefined. Это pos <= size().

Таким образом, язык определяет только то, что происходит в этом случае.

В следующем параграфе указано, что для pos < size() он возвращает ссылку на элемент в строке. И для pos == size() он возвращает ссылку на построенный по умолчанию charT со значением charT().

Хотя это может выглядеть как проверка границ, на практике фактически происходит то, что std::basic_string выделяет буфер больше, чем заданный, и заполняет последнюю запись с помощью charT(). Тогда [] просто делает арифметику указателя.

Я попытался найти способ избежать этой реализации. Хотя стандарт не предусматривает этого, я не мог бы убедить себя, что существует альтернатива. Было что-то раздражающее с .data(), из-за чего было трудно избежать одиночного буфера.

Ответ 4

Этот оператор стандартных контейнеров эмулирует поведение оператора [] обычных массивов. Поэтому он не делает никаких проверок. Однако в режиме отладки соответствующая библиотека может обеспечить эту проверку.

Если вы хотите проверить индекс, вместо этого используйте функцию-член at().

Ответ 5

http://en.cppreference.com/w/cpp/string/basic_string/operator_at

Возвращает ссылку на символ в указанном местоположении pos. Нет Выполняется проверка границ.

(Акцент мой).

Если вы хотите проверить границы, используйте std:: basic_string:: at

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

Если вы получаете доступ в пределах границ, он определен. Если вы выходите на улицу, вы вызываете поведение undefined.