среда, 12 августа 2009 г.

Книга Скотта Мейерса "Эффективное использование С++

Это первый мой обзор книги, который появился на rsdn почти год назад. Большую часть обзоров помимо rsdn я публикую и на блоге, поэтому, для полноты картины, решил, что обзор и этой книги здесь не помешает.
Если вы занимаетесь программированием на языке С++ несколько лет и не слышали об этой книге - значит вы не пытаетесь узнать ничего нового о своей профессии. Это одна из первых 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 страницы книги Б. Страуструпа, то эта книга, несомненно, для вас. Из недостатков хотелось бы отметить невысокое качество издания: не блещет и качество бумаги, да и в переводе попадаются неточности. Но в целом книга стоит того, чтобы за нее отдать деньги и потратить время на ее изучение.