Отключение проверки границ для векторов с ++ - PullRequest
11 голосов
/ 05 марта 2010

С stl :: vector:

vector<int> v(1);
v[0]=1; // No bounds checking
v.at(0)=1; // Bounds checking

Есть ли способ отключить проверку границ без необходимости переписывать все at() как []? Я использую стандартную библиотеку GNU C ++.

Редактировать : я изменил at() на [] в области, где я подозревал узкое место, и это значительно сократило время вычислений. Однако, поскольку я выполняю итерацию между разработкой кода и проведением экспериментов с ним, я хотел бы включить проверку границ во время разработки и отключить ее, когда я запускаю эксперименты по-настоящему. Я думаю, совет Эндрю - лучшее решение.

Ответы [ 8 ]

24 голосов
/ 05 марта 2010

Если вы действительно хотите это сделать (по крайней мере, для быстрого и грязного сравнения профилирования), это будет работать, если у вас нет других at() s

#define at(x) operator[](x)

А если вы хотите оставить at() для разработки и использовать operator[] в производстве, просто оберните его в #ifdef.

А если у вас есть другие at() s, вы всегда можете отредактировать файл #include d <vector>.

15 голосов
/ 05 марта 2010

Нет. Проверка границ std::vector::at определена стандартом, и не существует стандартной реализации C ++, которая могла бы отклониться от этого.

6 голосов
/ 05 марта 2010

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

5 голосов
/ 05 марта 2010

Исходя из вашего комментария о том, что вы хотите включить / отключить проверку границ, вы можете использовать функцию шаблона оболочки:

template <class T>
inline typename T::reference deref(T &cont, typename T::size_type idx)
{
#if BOUNDS_CHECK
    return cont.at(idx);
#else
    return cont[idx];
#endif
}

template <class T>
inline typename T::const_reference deref(const T &cont, typename T::size_type idx)
{
#if BOUNDS_CHECK
    return cont.at(idx);
#else
    return cont[idx];
#endif
}

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

Я признаю, что это выглядит немного уродливо:

deref(vec, 10) = ...;
3 голосов
/ 05 марта 2010

Не стандартным способом. Вы можете отключить исключения в вашем компиляторе. Вы можете сделать это с помощью gcc с помощью -fno-exceptions.

Вы должны быть осторожны с этим, хотя; Ваши библиотеки (в том числе стандартные библиотеки) могут работать некорректно с отключенными исключениями. Проверьте документацию и темы типа этот в списке рассылки gcc .

2 голосов
/ 26 декабря 2015

Используйте at(), когда вы всегда хотите проверить.Также обратите внимание, что это вызывает исключение при ошибке, поэтому оно потенциально может быть восстановлено.Если вам нужен более быстрый, непроверенный метод доступа, используйте [], но алгоритмы, использующие это, следует тщательно протестировать, поскольку режим отказа более серьезен (неопределенное поведение).

Параподходов к проверке границ в режиме разработки для [] при использовании GCC в Linux:

Некоторые другие интересные обсуждения: vector :: at vs. vector :: operator []

2 голосов
/ 05 марта 2010

Получите свой собственный векторный класс в своем собственном пространстве имен, например "uncheckedvector", и переопределите at () базового векторного типа, чтобы использовать индекс массива.

Тогда использование «using uncheckedvector :: vector» позволит вам переопределить все ваши использования вектора везде. Это не будет работать, если вы где-либо используете полностью определенные типы.

0 голосов
/ 05 марта 2010

Если у вас есть разумно согласованные шаблоны доступа (то есть / нет произвольного доступа), вместо использования at() или [], один из способов избежать проверки диапазона состоит в использовании итераторов, использующих begin(), end() и advance() или даже лучше, используя стандартные алгоритмы.

Хотя это не решает основную проблему исправления at() выполнения проверки диапазона, некоторые реализации стандартной библиотеки (MSVC) проверили итераторы для некоторых типов сборок

...