Должен ли класс выполнять проверку границ, когда вы после выступления - PullRequest
1 голос
/ 11 ноября 2010

Потенциально довольно субъективный вопрос, но здесь со мной все в порядке.

Скажем, у меня есть класс треугольника, определенный как

class Triangle{
vertex3D vertexs[3];
public:
vertex* GetVertex(int vertexNumber);
}

, теперь для большинства обычных приложений это довольно очевидноGetVertex должен убедиться, что vertexNumber является допустимым индексом, прежде чем пытаться вернуть указатель вершины.Я бы сказал, что обычно он может возвращать NULL, если vertexNumber недействительно, но это не совсем то, о чем я спрашиваю.

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

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

РЕДАКТИРОВАТЬ

Хорошо ... так что, если я пойду на проверку границ в отладке, но не в выпуске ... как я могу автоматизировать это?так что мне не нужно редактировать код ... какой-то переключатель времени компиляции или что-то в этом роде?будет ли работать #ifdef debug что-то вроде работы?где я могу найти больше об этом?

Ответы [ 8 ]

5 голосов
/ 11 ноября 2010

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

Если вы уверены, что ваш код верен (то есть, вы просмотрели код и тщательно его протестировали), тогда можно не использовать проверки границ в сборке релиза.производительности.

Если вы собираетесь тестировать границы в отладочной сборке, но не в сборке выпуска, то вам, вероятно, следует использовать assert в отладочной сборке.Утверждения должны быть использованы для проверки вещей, которые всегда верны.Если вы не проверяете границы внутри функции и ваш код верен, то значение никогда не должно выходить за пределы.

4 голосов
/ 11 ноября 2010

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

3 голосов
/ 11 ноября 2010

Если vertexNumber никогда не является значением, которое поступает напрямую от внешнего ввода, тогда я считаю, что вы можете предположить, что оно всегда допустимо - т.е. вы признаете существование контракта , говоря, что "эта функциябудет вести себя правильно, когда vertexNumber равен 0, 1 или 2 ".Тогда сам класс можно понимать как «правильный и безопасный» с точки зрения правильности кода, и вам нужно только беспокоиться о том, чтобы клиенты (пользователи этого класса) использовали его правильно, то есть не нарушали контракт.

Обычно идеальным инструментом для этого является использование assert () внутри методов класса для проверки выполнения контракта.Затем у вас будет проверка во время выполнения в debug сборке и вообще не будет проверок в release сборке.

2 голосов
/ 11 ноября 2010

Если этот класс находится в коде приложения (код, который используется только в одном приложении), измеряет , является ли повышение производительности значимым, а затем решает, удалять ли он проверки в Release Режим. (Оставьте их в режиме отладки.)

Если этот класс находится в коде библиотеки, это дизайнерское решение. Вы хотите, чтобы ваш класс был максимально безопасным или максимально быстрым ? Видя, что это графический код, вы, вероятно, хотите последний. (Это также стало популярным у STL, которая стремится к скорости.)

1 голос
/ 11 ноября 2010

Проектирование по контракту, Eiffel и книга «Построение объектно-ориентированного программного обеспечения, Майер» сказали бы, что вы должны определить проверки для связанных проблем, как это, как утверждения, которые вы можете скомпилировать из конечного продукта. Утверждения определяют математическую достоверность всей системы.

1 голос
/ 11 ноября 2010

Почему вы делаете Triangle объектом?Это выглядит как простой держатель данных.Не используется полиморфно.Это не имеет никакого поведения.Это не объект.Пусть это будет простая структура POD с общедоступными данными, , особенно , если вас беспокоит производительность.

Это дает дополнительный бонус: когда вызывающий абонент пытается использовать vertexNumber := 0xdeadbeef, нарушение доступапроисходит в неисправной вызывающей программе, пытающейся использовать массив публично, а не в безошибочной вспомогательной оболочке.Это может не иметь большого значения в среде отладки, но когда вы получаете отчет о сбое, который не включает в себя полную обратную трассировку, это проблема.углубленный rant обсуждение, которое я могу связать .

1 голос
/ 11 ноября 2010

.. довольно много времени .. небольшое повышение производительности

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

А если вы решите убрать проверку границ, то оформляйте по контракту :-)

1 голос
/ 11 ноября 2010

Я не думаю, что вообще не стоит проверять границы.Если вам важна производительность в этом случае, используйте хотя бы assert, который можно отключить в конфигурации выпуска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...