Читаем Эффективное использование STL полностью

 if(*i > x && *i < y)) break;      // элемента или достижения v.end

}

… // После завершения цикла

  // i указывает на искомый элемент

  // или совпадает с v.end

То же самое можно сделать и при помощи find_if, но для этого придется воспользоваться нестандартным адаптером объекта функции — например, compose2 из реализации SGI (см. совет 50):

vector::iterator i =

 find_if(v.begin, v.end,   // Найти первое значение val,

 compose2(logical_and, // для которого одновременно

 bind2nd(greater, x),   // истинны условия

 bind2nd(less, y)));    // val>x, и val

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

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

template

class BetweenValues:

 public unary_function { // См. совет 40

public:

 BetweenValues(const T& lowValue, const T& highValue) :

  lowVal(lowValue), highVal(highValue) {}

 bool operator(const T& val) const {

  return val > lowVal && val < highVal;

 }

private:

 T lowVal;

 T highVal;

};

vector iterator i = find_if(v.begin, v.end,

 BetweenValues(x, y));

Однако у такого решения имеются свои недостатки. Во-первых, создание шаблона BetweenValues требует значительно большей работы, чем простое написание тела цикла. Достаточно посчитать строки в программе: тело цикла — одна строка, BetweenValues — четырнадцать строк. Соотношение явно не в пользу алгоритма. Во-вторых, описание критерия поиска физически отделяется от вызова. Чтобы понять смысл вызова find_if, необходимо найти определение BetweenValues, но оно должно располагаться вне функции, содержащей вызов find_if. Попытка объявить BetweenValues внутри функции, содержащей вызов find_if:

{ // Начало функции

 …

 template

 class BetweenValues: public unary_function {…};

 vector::iterator i = find_if(v.begin, v.end,

  BetweenValues(x, у));

} // Конец функции

не компилируется, поскольку шаблоны не могут объявляться внутри функций. Если попробовать обойти это ограничение посредством реализации BetweenValues в виде класса:

{ // Начало функции

 …

 class BetweenValues: public unary_function {…};

 vector::iterator i = find_if(v.begin, v.end,

  BetweenValues(x, y));

} // Конец функции

все равно ничего не получается, поскольку классы, определяемые внутри функций, являются локальными, а локальные классы не могут передаваться в качестве аргументов шаблонов (как функтор, передаваемый find_if). Печально, но классы функторов и шаблоны классов функторов не разрешается определять внутри функций, как бы удобно это ни было.

В контексте борьбы между вызовами алгоритмов и циклами это означает, что выбор определяется исключительно содержимым цикла. Если алгоритм уже умеет делать то, что требуется, или нечто очень близкое, вызов алгоритма более нагляден. Если задача элементарно решается в цикле, а при использовании алгоритма требует сложных нагромождений адаптеров или определения отдельного класса функтора, вероятно, лучше ограничиться циклом. Наконец, если в цикле приходится выполнять очень длинные и сложные операции, выбор снова склоняется в пользу алгоритмов, потому что длинные и сложные операции лучше оформлять в отдельных функциях. После того как тело цикла будет перенесено в отдельную функцию, почти всегда удается передать эту функцию алгоритму (особенно часто — алгоритму for_each) так, чтобы полученный код был более наглядным и прямолинейным.

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

Успешная карьера архитектора программного обеспечения требует хорошего владения как технической, так и деловой сторонами вопросов, связанных с проектированием архитектуры. В этой необычной книге ведущие архитекторы ПО со всего света обсуждают важные принципы разработки, выходящие далеко за пределы чисто технических вопросов.?Архитектор ПО выполняет роль посредника между командой разработчиков и бизнес-руководством компании, поэтому чтобы добиться успеха в этой профессии, необходимо не только овладеть различными технологиями, но и обеспечить работу над проектом в соответствии с бизнес-целями. В книге более 50 архитекторов рассказывают о том, что считают самым важным в своей работе, дают советы, как организовать общение с другими участниками проекта, как снизить сложность архитектуры, как оказывать поддержку разработчикам. Они щедро делятся множеством полезных идей и приемов, которые вынесли из своего многолетнего опыта. Авторы надеются, что книга станет источником вдохновения и руководством к действию для многих профессиональных программистов.

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT