Несмотря на то что под ударами ультрамодных технологий поголовье программистов, работающих на языке C++, неуклонно сокращается, его в ближайшее время вряд ли удастся истребить окончательно.
Во многом такая живучесть объясняется спецификой ряда задач, решение которых требует создания кода, обеспечивающего комплексную эффективность. За длительный — по компьютерным меркам — период эксплуатации C++ накоплены методы, часто недоступные в других языках и во многом определяющие фундамент всего современного программирования.
Взять хотя бы шаблоны C++, которые не только позволили эффективно разрабатывать повторно используемый код, но и легли в основу обобщенного программирования (generic programming). Популярность этого подхода зарождалась в недрах стандартной библиотеки шаблонов STL (Standard Template Library). Как и положено, первой волной, посвященной STL, явились публикации, раскрывающие особенности ее организации и использования (см., например, Леен Аммераль, «STL для программистов на C++», М.: ДМК, 1999). Вместе с тем, необходимость практического использования библиотеки требует большего понимания ее достоинств и недостатков. Неудивительно, что в качестве советчика оказался признанный мастер этого жанра — Скотт Мейерс, который не только раскрыл технические особенности использования C++, но и показал, что для достижения эффективности полезно сочетать различные парадигмы программирования.
Практическое использование любого языка программирования заключается в освоении не только синтаксиса и семантики — необходимо хорошо знать библиотеки. Еще лучше, когда состав этих библиотек постоянно расширяется и совершенствуется. Языку C++ в этом отношении повезло, а STL является значимой промежуточной вехой на этом пути. Пятьдесят новых советов от Мейерса позволяют еще глубже понять не только принципы стандартной библиотеки шаблонов, но и один из путей дальнейшего развития техники программирования. В отличие, например, от книги Аммерааля, акцентирующей основное внимание на вопросе «что это такое», Мейерс в основном касается того, «как это эффективно использовать». Поэтому материал книги весьма полезен программистам-практикам.
Первая глава посвящена контейнерам, ради которых и создавалась библиотека. В частности, дается классификация как стандартных, так и нестандартных контейнеров, выделяются факторы, определяющие их выбор в зависимости от технических ограничений, рассматриваются способы эффективного использования. Показано, что не существует универсальных и эффективных механизмов; замена одного контейнера другим ведет к изменению кода. Предлагаются и практические советы, связанные с применением отдельных методов, например, для себя я уже решил, что в следующих приложениях, при проверке контейнеров на отсутствие элементов, вместо size буду использовать empty.
Во второй главе рассматриваются наиболее популярные объекты библиотеки, vector и string, приводятся способы повышения производительности при использовании векторов и строк. Показано, как исключить доступ к распределению памяти, обеспечить совместимость со строками языка Cи. Наряду с широко распространенными рекомендациями о предпочтении этих классов динамически выделяемым объектам, построенными на основе базовых типов C++, даются и более завуалированные советы. В частности, не использовать вектор булевых элементов, который не соотносится по всем параметрам с другими контейнерами STL.
Третья глава раскрывает особенности ассоциативных контейнеров, обеспечивающих эффективное хранение упорядоченных данных. Обращается внимание на различие между понятиями «равенство», используемом в последовательных контейнерах и «эквивалентность», применяемом в множествах и словарях (set и map). Думаю, что для программиста, использующего STL, очевидно переопределение операции сравнения в ассоциативных контейнерах, содержащих в качестве элементов указатели. Однако приведенная в книге информация помогает глубже понять суть вопроса. Ну и конечно, весьма полезными являются советы, посвященные эффективности использования.
К наиболее важным конструкциям STL относятся итераторы. Их организация не только во многом способствовала распространению библиотеки, но и послужила образцом для подражания. Четвертая глава акцентирует внимание на специфике их применения.
Алгоритмы — «мотор» STL. Их количество перевалило за 100. Одной из задач, решаемой в пятой главе, является описание ряда малоизвестных алгоритмов, которые, по мнению автора, облегчают жизнь программистов.
Одной из особенностей программирования, с которой мне впервые пришлось столкнуться в STL, является использование функторов — объектов, построенных на основе классов, но воспринимаемых как функции. Без них эффективное применение библиотеки становится практически невозможным. Поэтому, материал шестой главы, в которой проигрываются вариации на тему функторов, функциональных классов и функций, весьма познавателен. В частности рекомендуется использовать функциональные классы для передачи параметров по значению.
В седьмой главе рассматриваются вопросы комплексного использования программных объектов библиотеки. В частности, рекомендуется более внимательно изучить и использовать существующие алгоритмы, а не писать собственные циклы, осуществляющие пошаговую обработку элементов контейнеров. Еще раз подчеркивается, что есть из чего выбирать, и показывается, что встроенные в контейнеры функции предпочтительнее алгоритмов с соответствующими именами.
В приложении рассматриваются вопросы локализации применительно к STL и разбирается ряд проблем, связанных с использованием версии библиотеки, поставляемой с MS МС++ 6.0.
Книга полезна не только описанием стандартных объектов — в ней достаточно подробно рассмотрены контейнеры, использующие хеширование, однонаправленные списки и прочие технические приемы. Возможно, что многие из этих элементов будут включены в следующий стандарт библиотеки.
Scott Meyers. Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library. Addison-Wesley, 2001, p. 260, ISBN 0-201-74962-9