Система Orphus

Новые сложные задачи на C++

40 новых головоломных примеров с решениями

Автор: Герб Саттер
Издательство: Вильямс, 2005
270 страниц

Материал предоставил: Алексей Кирюшкин
Найти в магазинах
Купить в Озоне (230 руб.)

Аннотация

Содержание
Предисловие
Комментарии

Аннотация

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

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

Содержание

Предисловие

Стиль или суть?

Метод Сократа

Как читать данную книгу

Благодарности

Обобщенное программирование и стандартная библиотека C++

Задача 1. Вектор: потребление и злоупотребление
Вопрос для новичка
Вопрос для профессионала
Обращение к элементу вектора
Увеличение размера вектора
Резюме

Задача 2. Строчный двор. Часть 1: sprintf
Вопрос для новичка
Вопрос для профессионала
Радости и печали sprintf

Задача 3. Строчный двор. Часть 2: стандартные альтернативы
Вопрос для профессионала
Альтернатива №1: snprintf
Альтернатива №2: std::stringstream
Альтернатива №3: std::strstream
Альтернатива №4: boost::lexical_cast
Резюме

Задача 4. Функции-члены стандартной библиотеки
Вопрос для новичка
Вопрос для профессионала
Игры с mem_fun
Используйте mem_fun, но не со стандартной библиотекой
Использование указателей на функции-члены - но не со стандартной библиотекой
Резюме

Задача 5. Красота обобщенности. Часть 1: Азы
Вопрос для новичка
Вопрос для профессионала

Задача 6. Красота обобщенности. Часть 2: Достаточно ли универсальности?
Вопрос для профессионала

Задача 7. Почему не специализируются шаблоны функций?
Вопрос для новичка
Вопрос для профессионала
Перегрузка и специализация
Пример Димова-Абрамса
Мораль сей басни такова...
Резюме

Задача 8. Дружественные шаблоны
Вопрос для новичка
Вопрос для профессионала
Исходная попытка
В ''темных углах''
Причина 1: не всегда работает
Причина 2: удивляет программистов
Причина 3: удивляет компиляторы
Отступление: проблема в пространстве имен
Два неверных обходных пути
Резюме

Задача 9. Ограничения экспорта. Часть 1: основы
Вопрос для новичка
Вопрос для профессионала
Рассказ о двух моделях
Пояснение на примере
Использование экспорта
Проблема первая: открытый исходный текст
Проблема вторая: зависимости и время построения
Резюме

Задача 10. Ограничения экспорта. Часть 2: взаимосвязи, практичность и советы по использованию
Вопрос для новичка
Вопрос для профессионала
Начало: 1988-1996 гг.
1996 г.
Опыт работы с экспортом
До чего доводит экспорт
Трудность корректного использования
Потенциальные преимущества экспорта
Мораль

Вопросы и приемы безопасности исключений

Задача 11. Попробуй поймай
Вопрос для новичка
Вопрос для профессионала
Резюме

Задача 12. Безопасность исключений: стоит ли овчинка выделки?
Вопрос для профессионала
Гарантии Абрамса
Какая именно гарантия нужна

Задача 13. Прагматичный взгляд на спецификации исключений
Вопрос для новичка
Вопрос для профессионала
Нарушение спецификации
Применение
Проблема первая - призраки типов
Проблема вторая - (не)понимание
Копнем поглубже
Резюме

Разработка классов, наследование и полиморфизм

Задача 14. К порядку!
Вопрос для новичка
Вопрос для профессионала
Резюме

Задача 15. Потребление и злоупотребление правами доступа
Вопрос для новичка
Вопрос для профессионала
Преступник №1: фальсификатор
Преступник №2: карманник
Преступник №3: мошенник
Персона грата №4: адвокат
Не нарушай

Задача 16. Крепко закрыт?
Вопрос для профессионала
Доступность
Видимость
И снова доступность
Резюме

Задача 17. Инкапсуляция
Вопрос для новичка
Вопрос для профессионала
Место инкапсуляции в объектно-ориентированном программировании
Открытые, закрытые или защищенные данные?
Преобразование в общем случае
Актуальный момент
Резюме

Задача 18. Виртуальность
Вопрос для новичка
Вопрос для профессионала
Обычный совет о деструкторах базовых классов
Виртуальный вопрос №1: открытость или закрытость?
Виртуальный вопрос №2: деструкторы базовых классов
Резюме

Задача 19. Не можешь - научим, не хочешь - заставим!
Вопрос для новичка
Вопрос для профессионала
Неявно генерируемые функции
Спецификации исключений неявно определенных функций
Неявный конструктор по умолчанию
Неявный копирующий конструктор
Неявный копирующий оператор присваивания
Неявный деструктор
Член auto_ptr
Семейные проблемы
Не хочешь - заставим!
Резюме

Задача 20. Контейнеры в памяти. Часть 1: уровни управления памятью
Вопрос для новичка
Вопрос для профессионала
Диспетчеры памяти и их стратегии: краткий обзор
Выбор стратегии
Резюме

Задача 21. Контейнеры в памяти. Часть 2: какие они на самом деле?
Вопрос для новичка
Вопрос для профессионала
Что попросишь, то получишь?
Память и стандартные контейнеры: теория
Память и стандартные контейнеры: практика
Резюме

Задача 22. Новый взгляд на new. Часть 1: многоликий оператор new
Вопрос для новичка
Вопрос для профессионала
Размещающий, обычный и не генерирующий исключений оператор new
Оператор new, специфичный для класса
Сюрприз сокрытия имен
Резюме

Задача 23. Новый взгляд на new. Часть 2: прагматизм в управлении памятью
Вопрос для новичка
Вопрос для профессионала
Исключения, ошибки и new(nothrow)
Теория и практика
Что надо проверять
Резюме

Оптимизация и эффективность

Задача 24. Константная оптимизация
Вопрос для новичка
Вопрос для профессионала
const: ненавязчивый сервис
Как const может оптимизировать
Резюме

Задача 25. inline
Вопрос для новичка
Вопрос для профессионала
Краткий обзор
Ответ А: во время написания исходного текста
Ответ Б: во время компиляции
Ответ В: во время компоновки
Ответ Г: при инсталляции приложения
Ответ Д: в процессе работы
Ответ Е: в некоторое другое время
Резюме

Задача 26. Форматы данных и эффективность. Часть 1: игры в сжатие.
Вопрос для новичка
Вопрос для профессионала
Различные способы представления данных

Задача 27. Форматы данных и эффективность. Часть 2: игры с битами
Вопрос для профессионала
BitBuffer, убийца битов
Попытка №1: использование unsigned char
Попытка №2: использование стандартного контейнера упакованных битов
Плотная упаковка
Резюме

Ловушки, ошибки и головоломки

Задача 28. Ключевые слова, не являющиеся таковыми
Вопрос для новичка
Вопрос для профессионала
Зачем нужны ключевые слова
Ключевые слова C++
Зарезервированные комментарии
Резюме

Задача 29. Инициализация ли это?
Вопрос для новичка
Вопрос для профессионала
Базовый механизм заполнения
Не инициализация
Корректное заполнение
Резюме

Задача 30. Двойная точность - вежливость программистов
Вопрос для новичка
Вопрос для профессионала
Два слова о float и double
Колесо времени
О суживающем преобразовании типов
Резюме

Задача 31. Сумеречное состояние... кода
Вопрос для профессионала
Мотивация
Макросам наплевать...
Резюме

Задача 32. Небольшие очепятки и прочие курьезы
Вопрос для профессионала

Задача 33. Ооооператоры
Вопрос для новичка
Вопрос для профессионала
Правило ''максимального глотка''
Операторные шутки
Злоупотребление операторами
Дополнительный вопрос
Резюме

Изучение конкретных примеров

Задача 34. Индексные таблицы
Вопрос для новичка
Вопрос для профессионала
Небольшая проповедь о ясности
Разбор индексных таблиц
Исправление механических ошибок
Улучшение стиля
Резюме

Задача 35. Обобщенные обратные вызовы
Вопрос для новичка
Вопрос для профессионала
Качества обобщенности
Разбор обобщенных обратных вызовов
Улучшение стиля
Исправление механических ошибок и ограничений
Резюме

Задача 36. Объединения
Вопрос для новичка
Вопрос для профессионала
Основные сведения
Построение объединений
Разбор кода
Эти хитрые имена
Использование boost::апу
Размеченные объединения Александреску
Резюме

Задача 37. Ослабленная монолитность. Часть 1: взгляд на std::string
Вопрос для новичка
Вопрос для профессионала
Избегайте чрезмерно монолитных конструкций
Класс string
Резюме

Задача 38. Ослабленная монолитность. Часть 2: разбор std::string
Вопрос для новичка
Вопрос для профессионала
Членство - быть или не быть
Операции, которые обязаны быть членами
Операции, которые следует сделать членами
Спорные операции, которые могут не быть ни членами, ни друзьями

Задача 39. Ослабленная монолитность. Часть 3: уменьшение std::string
Вопрос для новичка
Вопрос для профессионала
Операции, которые могут не быть членами
resize
assign и +=/append/push_back
insert
Небольшой перерыв

Задача 40. Ослабленная монолитность. Часть 4: новый std::string
Вопрос для новичка
Вопрос для профессионала
Прочие операции, которые могут не быть членами
Небольшой перерыв на кофе
replace
Второй перерыв на кофе: сору и substr
compare
find
Резюме

Список литературы

Предметный указатель

Предисловие

Место действия: Будапешт. Жаркий летний вечер. Мы смотрим через Дунай, на восточный берег реки.

На обложке книги вы видите фото, на котором изображена эта пастельная европейская картина. Что первое бросается вам в глаза? Почти наверняка - здание парламента в левой части фотографии. Массивное неоготическое здание приковывает взгляд своим изящным куполом, массой вычурных шпилей, десятками статуй и прочими украшениями, контрастируя с простыми строгими линиями зданий на набережной Дуная.

Откуда же такое отличие? Строительство здания парламента было завершено в 1902 году, в то время как остальные здания на набережной были построены в разрушенном Будапеште после второй мировой войны.

"Ну и что же, - скажете вы, - какое отношение это имеет к книге?"

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

Стиль или суть?

Что же важнее? Чему лучше и правильнее отдать предпочтение? Вы уверены, что знаете точный ответ на этот вопрос? Так, понятие "лучше" лишено смысла, пока не определена мера, которой следует мерить. Лучше для чего? Лучше в какой ситуации? Скорее всего, ответ на этот вопрос представляет собой определенный компромисс и начинается со слов "Это зависит от..."

Это книга о поиске баланса между многими мелкими аспектами дизайна и реализации программ на C++. Глубокое знание ваших инструментов и исходных материалов весьма способствует пониманию того, когда их стоит использовать.

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

Так и в программировании - очень важно найти золотую середину между стоимостью и функциональностью, между элегантностью и сопровождаемостью, между возможностями развития и украшательством.

С подобными проблемами и поиском компромиссов мы вынуждены сталкиваться ежедневно при разработке программного обеспечения на C++. Среди вопросов, которые рассматриваются в данной книге, есть и такие: делает ли безопасность кода по отношению к исключениям лучше сам код? Если да - то что именно означает "делает его лучше", и не может ли возникнуть ситуация, когда это не так уж и хорошо? А как насчет инкапсуляции? Делает ли она программу лучше? Почему? При каких условиях это не так? Если вас заинтересовали эти вопросы - книга перед вами, прочтите ее. Кстати, встраиваемые функции - это хорошая оптимизация? Следует ли к ней прибегать? (Будьте очень-очень осторожны при ответе на этот вопрос.) Что общего между возможностью экспорта в C++ и зданием парламента? А между std::string и монолитной архитектурой зданий на набережной Дуная?

После рассмотрения множества различных технологий и возможностей C++, в конце книги целый раздел отведен для анализа реальных примеров опубликованных исходных текстов. Мы выясним, что авторам этих фрагментов удалось, что не совсем, и как исправить баланс между затрачиваемыми усилиями и хорошим стилем.

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

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

Метод Сократа

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

Эта книга вполне следует методу Сократа, как и ее предшественницы [SutterOO] и [SutterO2]. Предполагается, что вам приходится заниматься написанием промышленного программного обеспечения на языке C++; в книге используются вопросы и ответы для обучения эффективному применению стандарта C++ и его стандартной библиотеки, причем особое внимание уделяется разработке надежного программного обеспечения с использованием всех возможностей современного C++. Многие из рассмотренных в книге задач появились в результате работы автора и других программистов над своими программами. Цель книги - помочь читателю сделать верные выводы, как из хорошо известного ему материала, так и из только что изученного, и показать взаимосвязь между различными частями C++.

Данная книга не посвящена какому-то конкретному аспекту C++. Нельзя, однако, сказать, что она охватывает все детали C++ - для этого потребовалось бы слишком много книг, - но, тем не менее, в ней рассматривается широкая палитра возможностей C++ и стандартной библиотеки и, что немаловажно, демонстрируется, как кажущиеся на первый взгляд несвязанными между собой вещи могут совместно использоваться для получения новых решений старых и хорошо известных задач. Здесь вы найдете материал, посвященный шаблонам и пространствам имен, исключениям и наследованию, проектированию надежных классов и шаблонам проектирования, обобщенному программированию и магии макросов, - и не просто винегрет из этих вопросов, а задачи и решения, выявляющие взаимосвязь всех этих частей современного C++.

Эта книга продолжается с того места, где заканчивается изложение материала в [SutterOO] и [SutterO2], и следует той же традиции: материал книги подается в виде задач, сгруппированных по темам. Читатели первых книг найдут здесь наполненные новым содержанием уже знакомые им темы - безопасность исключений, обобщенное программирование, методы оптимизации и управления памятью. Основное внимание уделяется вопросам обобщенного программирования и эффективного использования стандартной библиотеки C++.

Большинство задач первоначально были опубликованы в Internet и некоторых журналах, в частности, это расширенные версии задач 63-86, которые можно найти на моем узле Guru of the Week [GotW], а также материалы, опубликованные мною в таких журналах, как C/C++ User Journal, Dr. Dobb's Journal, бывшем C++ Report и др. Последние исправления и дополнения к книге можно найти на Web-узле по адресу www.gotw.ca.

Комментарии

Алексей Кирюшкин

Пробежав глазами содержание и увидев там знакомые буквы export, sprintf, std::string, float и double, удержитесь от иронических замечаний насчет "Новых сложных баянов на C++" ( привет, _Winnie :) ), ибо школа Профессиональной игры на баянах имени Г.Саттера дорогого стоит.

На submit@rsdn.ru часто приходят вопросы типа "Опубликуете ли вы статью на тему X?" или "Будет ли вам интересна статья на тему Y?", так вот, любой баян, рассмотренный вами на уровне задач из этой книги, RSDN оторвет у вас вместе с руками :)