Чтение онлайн

на главную - закладки

Жанры

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Майерс Скотт

Шрифт:

Даже когда вы точно знаете, что хотите сделать, добиться желаемых результатов бывает нелегко. Значение какого типа должен возвращать оператор присваивания? Когда деструктор должен быть виртуальным? Как себя ведет оператор new, если не может найти достаточно памяти? Исключительно важно проработать подобные детали, поскольку иначе вы почти наверняка столкнетесь с неожиданным и даже необъяснимым поведением программы. Эта книга поможет вам избежать подобных ситуаций.

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

того правила, которое вас наиболее интересует, а затем следовать по ссылкам, чтобы посмотреть, куда они вас приведут.

Эта книга также не является введением в C++. В главе 2, например, я рассказываю о правильной реализации конструкторов, деструкторов и операторов присваивания, но при этом предполагаю, что вы уже знаете, что эти функции делают и как они объявляются. На эту тему существует множество книг по C++.

Цель этой книги – выделить те аспекты программирования на C++, которым часто не уделяют должного внимания. В других книгах описывают различные части языка. Здесь же рассказывается, как их комбинировать между собой для получения эффективных программ. В других изданиях говорится о том, как заставить программу откомпилироваться. А эта книга – о том, как избежать проблем, которых компилятор не в состоянии обнаружить.

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

Не найдете вы в этой книге и «Евангелия от C++» – единственно верного пути к идеальной программе на C++. Каждое правило – это рекомендация по тому или иному аспекту: как отыскать более удачный дизайн, как избежать типичных ошибок, как достичь максимальной эффективности, но ни один из пунктов не является универсально применимым. Проектирование и разработка программного обеспечения – это сложная задача, на которую оказывают влияние ограничения аппаратного обеспечения, операционной системы и приложений, поэтому лучшее, что я могу сделать, – это представить рекомендации по повышению качества программ.

Если вы систематически будете следовать всем рекомендациям, то маловероятно, что столкнетесь с наиболее частыми ловушками, подстерегающими вас в С++, но из любого правила есть исключения. Вот почему в каждом правиле приводятся пояснения. Они-то и составляют самую важную часть книги. Только поняв, что лежит в основе того или иного правила, вы сможете решить, насколько оно соответствует вашей программе с присущими только ей ограничениями.

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

Терминология

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

Объявление (declaration) сообщает компилятору имя и тип чего-либо, опуская некоторые детали. Объявления выглядят так:

extern int x; // объявление объекта

std::size_t numDigits(int number); // объявление функции

class Widget; // объявление класса

template<typename T> // объявление шаблона

class GraphNode; // (см. правило 42 о том, что такое «typename»

Заметьте, что я называю целое число x «объектом», несмотря на то что это переменная встроенного типа.

Некоторые люди под «объектами» понимают только переменные пользовательских типов, но я не принадлежу к их числу. Также отметим, что функция numDigits возвращает тип std::size_t, то есть тип size_t из пространства имен std. Это то пространство имен, в котором находится почти все из стандартной библиотеки C++. Однако, поскольку стандартная библиотека C (точнее говоря, С89) также может быть использована в программе на C++, символы, унаследованные от C (такие как size_t), могут существовать в глобальном контексте, внутри std, либо в обоих местах, в зависимости от того, какие заголовочные файлы были включены директивой #include. В этой книге я предполагаю, что с помощью #include включаются заголовочные файлы C++. Вот почему я употребляю std::size_t, а не просто size_t. Когда я упоминаю компоненты стандартной библиотеки вне текста программы, то обычно опускаю ссылку на std, полагая, что вы знаете, что такие вещи, как size_t, vector и cout, находятся в пространстве имен std. В примерах же программ я всегда включаю std, потому что в противном случае код не скомпилируется.

Кстати, size_t – это всего-навсего определенный директивой typedef синоним для некоторых беззнаковых типов, которые в C++ используются для разного рода счетчиков (например, количества символов в строках типа char*, количества элементов в контейнерах STL и т. п.). Это также тип, принимаемый функциями operator[] в векторах (vector), деках (deque) и строках (string). Этому соглашению мы будем следовать и при определении наших собственных функций operator[] в правиле 3.

В любом объявлении функции указывается ее сигнатура, то есть типы параметров и возвращаемого значения. Можно сказать, что сигнатура функции – это ее тип. Так, сигнатурой функции numDigits является std::size_t(int), иными словами, это «функция, принимающая int и возвращающая std::size_t». Официальное определение «сигнатуры» в C++ не включает тип возвращаемого функцией значения, но в этой книге нам будет удобно считать, что он все же является частью сигнатуры.

Определение (definition) сообщает компилятору детали, которые опущены в объявлении. Для объекта определение – это то место, где компилятор выделяет для него память. Для функции или шаблона функции определение содержит тело функции. В определении класса или шаблона класса перечисляются его члены:

int x; // определение объекта

std::size_t numDigits(int number) // определение функции

{ // (эта функция возвращает количество

std::size_t digitsSoFar = 1; // десятичных знаков в своем параметре)

while((number /= 10) != 0) ++digitsSoFar;

return digitsSoFar;

}

class Widget { // определение класса

public:

Widget;

~Widget;

...

};

template<typename T> // определение шаблона

class GraphNode {

public:

GraphNode;

~GraphNode;

...

};

Инициализация (initialization) – это процесс присваивания объекту начального значения. Для объектов пользовательских типов инициализация выполняется конструкторами. Конструктор по умолчанию (default constructor) – это конструктор, который может быть вызван без аргументов. Такой конструктор либо не имеет параметров вовсе, либо имеет значение по умолчанию для каждого параметра:

Поделиться:
Популярные книги

Адвокат Империи 3

Карелин Сергей Витальевич
3. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 3

Кротовский, может, хватит?

Парсиев Дмитрий
3. РОС: Изнанка Империи
Фантастика:
попаданцы
альтернативная история
аниме
7.50
рейтинг книги
Кротовский, может, хватит?

Дурная жена неверного дракона

Ганова Алиса
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Дурная жена неверного дракона

Вонгозеро

Вагнер Яна
1. Вонгозеро
Детективы:
триллеры
9.19
рейтинг книги
Вонгозеро

Ведьма Вильхельма

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
8.67
рейтинг книги
Ведьма Вильхельма

Папина дочка

Рам Янка
4. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Папина дочка

Законы Рода. Том 6

Flow Ascold
6. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Законы Рода. Том 6

Как я строил магическую империю 7

Зубов Константин
7. Как я строил магическую империю
Фантастика:
попаданцы
постапокалипсис
аниме
фантастика: прочее
5.00
рейтинг книги
Как я строил магическую империю 7

Лучший из худший 3

Дашко Дмитрий
3. Лучший из худших
Фантастика:
городское фэнтези
попаданцы
аниме
6.00
рейтинг книги
Лучший из худший 3

Штурмовик из будущего 3

Политов Дмитрий Валерьевич
3. Небо в огне
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Штурмовик из будущего 3

Последний попаданец 2

Зубов Константин
2. Последний попаданец
Фантастика:
юмористическая фантастика
попаданцы
рпг
7.50
рейтинг книги
Последний попаданец 2

Идеальный мир для Лекаря 14

Сапфир Олег
14. Лекарь
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 14

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Вдова на выданье

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Вдова на выданье