Отключение проверки границ для векторов С++

С stl::vector:

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

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

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


person matthiash    schedule 05.03.2010    source источник
comment
С какой целью? Может быть лучший способ.   -  person i_am_jorf    schedule 05.03.2010
comment
Вы должны иметь возможность использовать регулярное выражение для замены at() на [] и установить точку останова, чтобы убедиться, что все экземпляры были заменены. Не то, чтобы одно проскальзывание было бы катастрофой, проблема заключается только в производительности, верно?   -  person Potatoswatter    schedule 05.03.2010
comment
Почему вы хотите это сделать? Если ваш ответ — производительность, скажите, что вы профилировали и обнаружили, что это ваше узкое место. Если это так, то да, перепишите at() как []. В противном случае пусть будет.   -  person Adam Rosenfield    schedule 05.03.2010
comment
@Adam: И не все at, а только горячие точки. :-П   -  person Chris Jester-Young    schedule 05.03.2010
comment
@Adam: я профилировал его с помощью oprofile, и программа использует много времени в libstdc++, поэтому я хочу проверить, связано ли это с проверкой границ. Я хочу сохранить проверку границ во время разработки, но, возможно, отключу ее, когда буду запускать ее по-настоящему.   -  person matthiash    schedule 05.03.2010
comment
Вы должны определить точное местоположение узкого места. Возможно, ваш код проводит 80% времени в malloc(), не имея ничего общего с проверкой границ :)   -  person Sad Developer    schedule 05.03.2010


Ответы (8)


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

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

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

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

person Andrew Stein    schedule 05.03.2010
comment
+1 Опоздал на вечеринку, но дал отличный совет. Это определенно быстрый и грязный способ профилировать что-то. - person Chris Lutz; 05.03.2010

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

person Chris Jester-Young    schedule 05.03.2010

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

person Fred Larson    schedule 05.03.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) = ...;
person R Samuel Klatchko    schedule 05.03.2010
comment
Это должен быть принятый ответ, поскольку он работает хорошо и не нарушает несвязанный код, как решение Эндрю Штейна с #define. - person BullyWiiPlaza; 12.12.2018

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

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

person Matt Curtis    schedule 05.03.2010

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

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

Еще одно интересное обсуждение: vector::at vs. vector::operator[]

person Brent Bradburn    schedule 26.12.2015

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

Затем используйте «using uncheckedvector::vector», чтобы вы могли везде переопределить все ваши варианты использования вектора. Однако это не сработает, если вы где-нибудь используете полные типы.

person SPWorley    schedule 05.03.2010
comment
-1: никогда не наследуются от типов STL, в них отсутствуют виртуальные деструкторы. - person Joh; 12.04.2012

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

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

person Andrew Walker    schedule 05.03.2010