В чем разница между #include <filename> и #include "filename" в C++?
Разница между #include <filename> и #include "filename"
Главное отличие заключается в путях поиска файлов, которые использует препроцессор C++. Это не просто стиль кода, а строго определённое поведение, описанное в стандарте C++.
Как работает #include <filename>
Угловые скобки указывают препроцессору искать файл только в системных директориях (стандартных путях компилятора). Обычно это:
- Стандартные каталоги компилятора (например,
/usr/includeв Linux илиC:\Program Files\Microsoft Visual Studio\...\includeв Windows). - Пути, указанные через флаг
-I(GCC/Clang) или/I(MSVC) при компиляции.
Этот вариант не ищет файл в текущей директории проекта (если она не добавлена в системные пути).
Как работает #include "filename"
Кавычки указывают препроцессору начать поиск с директории, содержащей текущий файл (где находится директива #include). Стандартный порядок:
- Директория текущего файла (implementation-defined, но обычно это папка с исходником).
- Если не найден — поиск в системных директориях (как в случае с угловыми скобками).
То есть #include "iostream" сначала проверит папку проекта, не найдёт там iostream, а затем найдёт его в системных путях — поэтому и работает. Но это плохая практика.
Почему #include <myheader.h> не работает?
Потому что в системных директориях нет вашего файла myheader.h. Вы не добавляли его туда, и компилятор не знает, где его искать. Чтобы использовать угловые скобки для своих файлов, нужно:
- Либо добавить путь к папке с
myheader.hчерез флаг-I(например,g++ -I./include main.cpp). - Либо поместить файл в одну из системных директорий (не рекомендуется).
Примеры кода для наглядности
Предположим, структура проекта:
project/
├── main.cpp
├── myheader.h
└── lib/
└── util.h
В main.cpp:
#include "myheader.h" // OK — найдёт в той же папке
#include "lib/util.h" // OK — можно указывать относительный путь
#include <myheader.h> // Ошибка — файл не в системных путях
#include <util.h> // Ошибка — даже не знает про папку lib
Если скомпилировать с флагом -I:
g++ -I./lib main.cpp
Тогда #include <util.h> начнёт работать, потому что ./lib добавлен в системные пути.
Практические рекомендации
- Системные/стандартные заголовки (iostream, vector, string, cmath) — всегда используйте
#include <filename>. Это быстрее, однозначно и понятно. - Свои заголовки — используйте
#include "filename". Это гарантирует поиск в текущей папке проекта. - Библиотеки третьих сторон — используйте угловые скобки, если путь к ним добавлен через
-Iили в переменную окружения.
Влияние на производительность
Разница в скорости компиляции минимальна. Поиск файлов — операция быстрая. Но логически угловые скобки работают чуть быстрее, так как не проверяют текущую директорию. Однако это не причина для беспокойства.
Итог: используйте угловые скобки для стандартных и системных заголовков, кавычки — для своих. Это стандарт де-факто, принятый во всём сообществе C++.
<<Альтернативный взгляд: разница с точки зрения переносимости
Помимо технической разницы в поиске файлов, есть важный аспект переносимости кода между разными компиляторами и операционными системами.
Поведение может отличаться
Стандарт C++ (раздел [cpp.include]) определяет только общие принципы:
#include <filename>— поиск в "implementation-defined" местах (обычно системные пути).#include "filename"— сначала поиск в "implementation-defined" месте (обычно директория текущего файла), затем как в первом случае.
Но формулировка "implementation-defined" означает, что разные компиляторы могут вести себя слегка по-разному. Например:
- В GCC и Clang
"filename"сначала ищет в папке с текущим файлом, затем в системных путях. - В MSVC (Visual Studio) поведение аналогично, но есть нюансы: если файл не найден в папке с исходником, поиск идёт по путям, указанным в настройках проекта.
- Некоторые старые компиляторы могли искать
"filename"только в текущей папке, без fallback на системные пути.
Практический совет
Чтобы избежать проблем с переносимостью:
- Всегда используйте кавычки для своих заголовков — это гарантирует поиск в проекте независимо от настроек компилятора.
- Всегда используйте угловые скобки для стандартных заголовков — это явно указывает, что файл системный.
- Избегайте смешивания: не пишите
#include "iostream"— это сбивает с толку других разработчиков и может привести к ошибкам, если в папке проекта вдруг появится файл с таким же именем.
Помните: код читают люди, а не только компилятор. Следование конвенциям делает ваш код понятным и предсказуемым для всех.
Ответов пока нет.
Войдите чтобы оставить ответ