Директива #include обрабатывается препроцессором до компиляции и работает
буквально: содержимое указанного файла подставляется на место директивы.
Никакой «загрузки библиотеки» не происходит — это текстовая вставка, а не
команда «во время запуска открыть другой файл с кодом».
#include <iostream> // системный заголовок: ищется в путях компилятора
#include "my_code.h" // свой: сначала ищется рядом с текущим файломУгловые скобки — для стандартной библиотеки и внешних библиотек, кавычки — для собственных файлов проекта. Конкретные правила поиска зависят от инструментов и настроек сборки.
Увидеть результат подстановки можно своими глазами: после g++ -E main.cpp
вместо десятка написанных строк окажутся тысячи строк из подключённых
заголовков. Заголовки сами подключают другие заголовки, поэтому разрастание
нормально. См. Компиляция и сборка.
Что ещё умеет препроцессор
Кроме подключения файлов — макроподстановки:
#define TWO 2
int main() {
return TWO + TWO * TWO;
}После обработки директивы в выражении окажутся обычные двойки. TWO — не
переменная: у неё нет ни объекта, ни адреса, ни значения, меняющегося во время
выполнения. Это имя макроса, используемое при обработке исходного текста.
Подстановка работает с элементами текста, а не заменяет любые совпавшие
подстроки: TWO внутри "TWO" останется частью строкового литерала. На курсе
макросы вряд ли понадобятся, но знать, что #define и переменная — разные
вещи, стоит.
Заголовки, которые встречаются сразу
| Заголовок | Что даёт |
|---|---|
<iostream> | std::cin, std::cout, std::cerr |
<iomanip> | std::setw, std::setfill, std::setprecision |
<cmath> | std::sqrt, std::abs, std::round, std::pow |
<limits> | std::numeric_limits<T>::max() и min() |
<cstdint> | int32_t, int64_t и другие типы фиксированной ширины |
<string> | std::string |
<vector> | std::vector |
Правило «подключай то, что используешь»
Каждый файл подключает заголовки для всего, что в нём упомянуто, — и не
подключает лишнего. Заголовки тянут друг друга, поэтому std::sqrt может
случайно оказаться доступен и без <cmath>; но это случайность конкретной
реализации, и на другой платформе сборка сломается.
Обратное тоже верно: неиспользуемый #include — мусор, который замедляет
компиляцию и вводит читателя в заблуждение.
Порядок и стиль
Google Style Guide задаёт порядок групп, разделённых пустой строкой: собственный заголовок этого файла, заголовки C, заголовки C++, чужие библиотеки, свои файлы проекта. Внутри группы — по алфавиту:
#include <cmath>
#include <iostream>clang-format умеет это сортировать сам: достаточно запустить его с флагом
-i, и порядок будет приведён к требуемому.
Тонкости
- Заголовки C++ для функций из C пишутся без
.hи с префиксомc:<cmath>, а не<math.h>. Тогда имена попадают в пространствоstdи вызываются какstd::sqrt. - В
<cmath>доступны иstd::sqrt, и глобальныйsqrt. Смешивать не стоит — пишите вездеstd::. - Многократное включение одного заголовка безопасно: внутри стоит защита
(
#pragma onceили include guard). В своих заголовках её нужно ставить самому. - Посмотреть, во что превращается файл после препроцессора:
g++ -E file.cpp | less.
Частые ошибки
- Забыть
<iomanip>и получить ошибку проsetw— при том что<iostream>подключён. - Оставить
#include <cmath>после того, как математику из кода убрали. - Подключить
<math.h>вместо<cmath>и потерятьstd::.