Сообщений 6    Оценка 5        Оценить  
Система Orphus

Эффективное использование C++.

55 верных советов улучшить структуру и код ваших программ

Автор: Скотт Мейерс
Издательство: "ДМК пресс", 2006
300 страниц
ISBN: 5-94074-304-8
ISBN: 0-321-33487-6

Материал предоставил: Сергей Тепляков
Найти в магазинах
Купить в Озоне (182 руб.)

Аннотация

Содержание
Комментарии

Аннотация

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

Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Содержание

Благодарности
Предисловие
Введение
Терминология
Соглашение об именах
Многопоточность
Библиотеки TR1 и Boost

Глава 1. Приучайтесь к С++

Правило 1: Относитесь к С++ как к конгломерату языков
Правило 2: Предпочитайте const, enum и inline использованию #define
Правило 3: Везде, где только можно, используйте const
Правило 4: Прежде чем использовать объекты, убедитесь, что они инициализированы

Глава 2. Конструкторы, деструкторы и операторы присваивания

Правило 5: Какие функции С++ создает и вызывает молча
Правило 6: Явно запрещайте компилятору генерировать функции, которые вам не нужны
Правило 7: Объявляйте деструкторы виртуальными в полиморфном базовом классе
Правило 8: Не позволяйте исключениям покидать деструкторы
Правило 9: Никогда не вызывайте виртуальные функции в конструкторе или деструкторе
Правило 10: Операторы присваивания должны возвращать ссылку на *this
Правило 11: В operator= осуществляйте проверку на присваивание самому себе
Правило 12: Копируйте все части объекта

Глава 3. Управление ресурсами

Правило 13: Используйте объекты для управления ресурсами
Правило 14: Тщательно продумывайте поведение при копировании классов, управляющих ресурсами
Правило 15: Предоставляйте доступ к самим ресурсам из управляющих ими классов
Правило 16: Используйте одинаковые формы new и delete
Правило 17: Помещение в ''интеллектуальный'' указатель объекта, выделенного с помощью new, лучше располагать в отдельном предложении

Глава 4. Проектирование программ и объявления

Правило 18: Проектируйте интерфейсы так, что их легко было использовать правильно и трудно - неправильно
Правило 19: Рассматривайте проектирование класса как проектирование типа
Правило 20: Предпочитайте передачу по ссылке на const передачу по значению
Правило 21: Не пытайтесь вернуть ссылку, когда должны вернуть объект
Правило 22: Объявляйте данные-члены закрытыми
Правило 23: Предпочитайте функциям-членам функции, не являющиеся ни членами, ни друзьями класса
Правило 24: Объявляйте функции, не являющиеся членами, когда преобразование типов должно быть применимо ко всем параметрам
Правило 25: Подумайте о поддержке функции swap, не возбуждающей исключений

Глава 5. Реализация

Правило 26: Откладывайте определение переменных насколько возможно
Правило 27: Не злоупотребляйте приведением типов
Правило 28: Избегайте возвращения ''дескрипторов'' внутренних данных
Правило 29: Стремитесь, чтобы программа была безопасна относительно исключений
Правило 30: Тщательно обдумывайте использование встроенных функций
Правило 31: Уменьшайте зависимости файлов при компиляции

Глава 6. Наследование и объектно-ориентированное проектирование

Правило 32: Используйте открытое наследование для моделирования отношения ''является''
Правило 33: Не скрывайте унаследованные имена
Правило 34: Различайте наследование интерфейса и наследование реализации
Правило 35: Рассмотрите альтернативы виртуальным функциям
Правило 36: Никогда не переопределяйте наследуемые невиртуальные функции
Правило 37: Никогда не переопределяйте наследуемое значение аргумента функции по умолчанию
Правило 38: Моделируйте отношение ''содержит'' или ''реализуется посредством'' с помощью композиции
Правило 39: Продумывайте подход к использованию закрытого наследования
Правило 40: Продумывайте подход к использованию множественного наследования

Глава 7. Шаблоны и обобщенное программирование

Правило 41: Разберитесь в том, что такое неявные интерфейсы и полиморфизм на этапе компиляции
Правило 42: Усвойте оба значения ключевого слова typename
Правило 43: Необходимо знать, как обращаться к именам в шаблонных базовых классах
Правило 44: Размещайте независимый от параметров код вне шаблонов
Правило 45: Разрабатывайте шаблоны функций-членов так, чтобы они принимали ''все совместимые типы''
Правило 46: Определяйте внутри шаблонов функции, не являющиеся членами, когда желательны преобразования типа
Правило 47: Используйте классы-характеристики для предоставления информации о типах
Правило 48: Изучите метапрограммирование шаблонов

Глава 8. Настройка new и delete

Правило 49: Разберитесь в поведении обработчика new
Правило 50: Когда имеет смысл заменять new и delete
Правило 51: Придерживайтесь принятых соглашений при написании new и delete
Правило 52: Если вы написали оператор new с размещением, напишите и соответствующий оператор delete

Глава 9. Разное

Правило 53: Обращайте внимание на предупреждения компилятора
Правило 54: Ознакомьтесь со стандартной библиотекой, включая TR1
Правило 55: Познакомьтесь с Boost

Приложение А. За пределами ''Эффективного использования С++''
Приложение В. Соответствие правил во втором и третьем изданиях

Комментарии

Сергей Тепляков

Если вы занимаетесь программированием на языке С++ несколько лет и не слышали об этой книге - значит вы не пытаетесь узнать ничего нового о своей профессии. Это одна из первых advanced книг, которая появилась на свет. Книга подразумевает, что вы уже знакомы с синтаксисом языка, немного поработали на нем и хотите поднять свои знания на следующий уровень. Не зря автор пишет: ''Одно дело - изучать фундаментальные основы языка, и совсем другое - учиться проектировать и реализовывать эффективные программы. В особенности это касается С++, известного необычайно широкими возможностями и выразительностью.>. Основная цель книги: ''показать вам, как применять С++ эффективно''. Под ''эффективностью'' в данном случае подразумевается не только эффективность исполнения написанного кода, но и эффективность проектирования программного обеспечения и непосредственной разработки на С++.

Эта книга относится к той категории, которую лучше всего опишет цитата Коплиена: ''Синтаксис языка до определенной степени формирует наше восприятие, но простое описание синтаксиса в ''руководстве пользователя'' станет всего лишь отправной точкой. Структура наших программ (а следовательно, и тех систем, которые мы строим) в основном определяется стилем и идиомами, используемыми для выражения архитектурных концепций''.

Именно различным идиомам языка программирования С++ автор и уделяет основное внимание.

Вот, например, что вы можете сказать о следующем фрагменте кода:

int priority();
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);

...
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());

Сколько программистов увидят здесь утечку памяти (конечно, все, кто читал книги Герба Саттера, но не будем об этом)? Да, утечка памяти здесь возможна, т.к. порядок вычисления аргументов функции не определен, и вполне вероятно следующее:

  1. Выполнение new Widget
  2. Вызов функции priority()
  3. Вызов конструктора tr1::shared_ptr

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

А такой пример:

class Widget {

public:

  ...

  static void* operator new(std::size_t size,              // необычная
                            std::ostream& logStream)       // форма new
    throw(std::bad_alloc);

  static void operator delete(void *pMemory                // обычная
                              std::size_t size) throw();   // форма delete
                                                           // уровня класса
  ...

};

И если где-то в коде встретится:

Widget *pw = new (std::cerr) Widget;

То, при генерации исключения конструктором, происходит гарантированная утечка памяти.

Кроме этого автор поднимает такие вопросы, как физическая и логическая константность, проблему инициализации нелокальных статических объектов, идиому ''захват ресурсов есть инициализация'' (Resource Acquisition Is Initialization - RAII), проблему сокрытия имен и многие другие.

В новом издании добавлены вопросы безопасности исключений (три вида гарантии исключений, перекачивали из книг Герба Саттера). Вот, что автор пишет по этому поводу: ''Женщина либо беременна, либо нет. Невозможно быть чуть-чуть беременной. Аналогично программная система является либо безопасной по исключениям, либо нет. Нет такого понятия, как частично безопасная система. Если система имеет всего одну небезопасную относительно исключений функцию, то она небезопасна и в целом.''.

Также большое внимание уделяется грядущим дополнениям языка, в частности std::tr1::shared_ptr, std::tr1::function, std::tr1::bind, не забыт и boost.

В книге описаны проблемы, с которыми сталкивается каждый профессиональный разработчик, и конечно программист с достаточным опытом все эти проблемы уже испытал на себе и едва ли найдет большое количество новой информации, но повторить какие-то языковые идиомы - тоже не лишне. Если же ваш опыт не достиг заоблачных высот, вы не выучили на зубок книги Г. Саттера, А. Александреску, Д. Элджера, Дж. Коплиента и не можете среди ночи процитировать первый абзац 527 страницы книги Б. Страуструпа, то эта книга, несомненно, для вас.

Из недостатков хотелось бы отметить невысокое качество издания: не блещет и качество бумаги, да и в переводе попадаются неточности. Но в целом книга стоит того, чтобы за нее отдать деньги и потратить время на ее изучение.

    Сообщений 6    Оценка 5        Оценить