Avatar ·

Разница между #include <filename> и #include "filename" в C++

Всем привет! Я только начал изучать C++ и столкнулся с непонятным моментом. В разных учебниках и примерах я вижу, что заголовочные файлы подключаются двумя разными способами: с угловыми скобками `#include ` и с кавычками `#include "myheader.h"`. Я понимаю, что оба варианта работают, но мне неясно, в чём принципиальная разница. Когда нужно использовать угловые скобки, а когда кавычки? Влияет ли это на скорость компиляции или на то, где компилятор ищет файлы? Я пробовал писать `#include "iostream"` — и оно тоже сработало (я использую Visual Studio). Значит ли это, что разницы вообще нет? Особенно меня смущает, когда я создаю свой собственный заголовочный файл, например, `utils.h`, который лежит в той же папке, что и `main.cpp`. Я видел, что некоторые пишут `#include "utils.h"`, а другие — `#include `. Какой вариант правильный? И что произойдёт, если я перепутаю? Заранее спасибо за разъяснения! Пример моего кода: ```cpp // main.cpp #include // так подключают стандартные библиотеки #include "myheader.h" // а так — мои собственные файлы int main() { std::cout << "Hello, World!" << std::endl; return 0; } ``` <<>>

Основное различие: пути поиска файлов

Главное отличие между #include <filename> и #include "filename" заключается в том, где компилятор ищет указанный файл. Это поведение определено стандартом C++ и реализовано во всех компиляторах (GCC, Clang, MSVC и др.).

1. Угловые скобки: #include <filename>

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

  • /usr/include (Linux/macOS)
  • C:\Program Files\Microsoft Visual Studio\...\include (Windows)
  • Пути, указанные через флаг -I (GCC/Clang) или /I (MSVC)

Пример: #include <iostream>, #include <vector>, #include <cstdio>.

2. Кавычки: #include "filename"

Эта форма предназначена для пользовательских (локальных) заголовочных файлов. Компилятор сначала ищет файл в той же директории, где находится исходный файл, который содержит директиву #include. Если файл там не найден, поиск продолжается в системных директориях (как в случае с угловыми скобками).

Пример: #include "myheader.h", #include "utils/config.h".

Важные нюансы и примеры

Рассмотрим ситуацию: у вас есть проект со структурой:

project/
├── main.cpp
├── myheader.h
└── include/
    └── myheader.h  (другая версия)

Если в main.cpp написать #include "myheader.h", компилятор сначала найдёт project/myheader.h. Если написать #include <myheader.h>, он будет искать в системных путях и, возможно, не найдёт файл вовсе (если не указать -I project).

Почему #include "iostream" работает?

Если вы написали #include "iostream" и это сработало, значит компилятор не нашёл файл iostream в текущей папке (там его нет) и перешёл к поиску в системных директориях, где и обнаружил стандартный заголовок. Это неправильная практика, так как:

  • Замедляет компиляцию (лишний поиск в текущей папке).
  • Может привести к ошибкам, если в текущей папке случайно окажется файл с таким же именем (например, злонамеренный iostream).

Рекомендации

  • Для стандартных библиотек — всегда используйте угловые скобки: #include <iostream>.
  • Для своих заголовков — всегда используйте кавычки: #include "myheader.h".
  • Для сторонних библиотек — обычно угловые скобки, если библиотека установлена в систему, или кавычки с указанием относительного пути, если она лежит рядом с проектом.

Пример правильного использования

// main.cpp
#include <iostream>      // стандартная библиотека
#include <vector>        // стандартная библиотека
#include "myheader.h"     // мой собственный заголовок
#include "../lib/utils.h" // заголовок из соседней папки

int main() {
    std::cout << myFunction() << std::endl;
    return 0;
}

Запомните: угловые скобки — для системного, кавычки — для своего. Это правило сделает ваш код переносимым и понятным для других разработчиков.

<<>>

Дополнение: настройка путей поиска и флаги компилятора

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

Для угловых скобок

Флаг -I (GCC/Clang) или /I (MSVC) добавляет директории в список поиска для #include <>. Например:

g++ -I/usr/local/include -I./third_party main.cpp

Теперь #include <mylib.h> будет искать файл в /usr/local/include, ./third_party и стандартных путях.

Для кавычек

Если вы используете #include "file.h", а файл лежит не в той же папке, можно указать относительный или абсолютный путь прямо в директиве:

#include "include/file.h"   // относительно текущей папки
#include "../shared/file.h" // подняться на уровень выше

Или добавить директорию через -iquote (GCC/Clang) — это добавит путь только для кавычек, не влияя на угловые скобки:

g++ -iquote./include main.cpp

Теперь #include "file.h" будет искать в ./include в первую очередь.

Практический совет

Для больших проектов используйте флаг -I для добавления корневых директорий с заголовками, а в коде пишите #include <module/submodule.h>. Это делает пути единообразными и не зависит от расположения исходного файла. Кавычки же оставьте для быстрых экспериментов или очень маленьких проектов.