Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Саттер Герб. Стандарты программирования на С++. 101 правило и рекомендация - royallib.ru.doc
Скачиваний:
59
Добавлен:
11.03.2016
Размер:
715.24 Кб
Скачать

84. Предпочитайте вызовы алгоритмов самостоятельно разрабатываемым циклам Резюме

Разумно используйте функциональные объекты. В очень простых случаях написанные самостоятельно циклы могут оказаться более простым и эффективным решением. Тем не менее, вызов алгоритма вместо самостоятельно разработанного цикла может оказаться более выразительным, легче сопровождаемым, менее подверженным ошибкам и не менее эффективным.

При вызове алгоритма подумайте о написании собственного функционального объекта, который инкапсулирует всю необходимую логику. Избегайте объединения связывателей параметров и простых функциональных объектов (например, bind2nd, plus), что обычно снижает ясность кода. Подумайте об использовании лямбда-библиотеки [Boost], которая автоматизирует задачу написания функциональных объектов.

Обсуждение

Программы, которые используют STL, имеют тенденцию к меньшему количеству явных циклов, чем у программ без применения STL благодаря замене низкоуровневых циклов высокоуровневыми абстрактными операциями с существенно большей семантикой. При программировании с использованием STL, следует думать не в категориях "как обработать каждый элемент", а "как обработать диапазон элементов".

Главное преимущество алгоритмов и шаблонов проектирования в общем случае заключается в том, что они позволяют нам говорить на более высоком уровне абстракции. В современном программировании мы не говорим "пусть несколько объектов следят за одним объектом и получают автоматические уведомления при изменении его состояния". Вместо этого мы говорим просто о "шаблоне проектирования Observer". Аналогично, мы говорим "Bridge", "Factory" и "Visitor". Использование словаря шаблонов проектирования позволяет повысить уровень, эффективность и корректность нашего обсуждения. Точно так же при использовании алгоритмов мы не говорим "выполняем действие над каждым элементом диапазона и записываем результат в некоторое место"; вместо этого мы говорим просто — transform. Аналогично, мы можем сказать for_each, replace_if и partition. Алгоритмы, подобно шаблонам проектирования, самодокументируемы. "Голые" циклы for и while ничего не говорят о том, для чего они предназначены, и читателю приходится изучать тела циклов, чтобы расшифровать их семантику.

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

И наконец, алгоритмы зачастую также более эффективны, чем простые циклы (см. [Sutter00] и [Meyers01]). В них устранены небольшие неэффективности, такие как повторные вычисления container.end()). Не менее важно, что стандартные алгоритмы, используемые вами, были реализованы теми же программистами, кто реализовывал и используемые вами стандартные контейнеры, и понятно, что их знание конкретных реализаций позволяет им написать алгоритмы более эффективно, чем это сможете сделать вы. Важнее всего, однако, то, что многие алгоритмы имеют высокоинтеллектуальные реализации, которые мы никогда не сможем реализовать в собственноручно разработанном коде (не считая случаев, когда нам не нужна та степень обобщенности, которую предоставляют алгоритмы). Вообще говоря, более используемая библиотека всегда оказывается лучше отлаженной и более эффективной просто потому, что у нее больше пользователей. Вряд ли вы найдете и сможете использовать в своей программе библиотеку, настолько же широко применяемую, как и реализация вашей стандартной библиотеки. Воспользуйтесь ею. Алгоритмы STL уже написаны — так почему бы не воспользоваться ими?

Подумайте об использовании лямбда-функций [Boost]. Лямбда-функции представляют собой важный инструмент, который позволяет справиться с основным недостатком алгоритмов, а именно с удобочитаемостью. Без их применения вы должны использовать либо функциональные объекты (но тогда тела даже простых циклов находятся в отдельном месте, далеко от точки вызова), либо стандартные связыватели и функциональные объекты наподобие bind2nd и plus (достаточно запутанные, сложные и утомительные в использовании).