Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60

Extern и функции с компоновкой по правилам языка С++

12.10.2025, 12:32. Показов 2541. Ответов 20
Метки c++ (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день,

Разобрался с модульным построением программ (через пространства имен) и раздельной компиляцией, понимаю что в заголовочных файлах нужно объявлять переменные с модификатором extern, а определять их в единственном месте в соответствующем *.cpp файле. Пишу программы в таком стиле и они работают.

Но не могу понять следующего: для чего и в каких функциях использовать extern при объявлении функции, компонуемых в соответствии с правилами языка c++. Тут не веду речь об extern "C", с ним то как раз все ясно. Мои программы прекрасно работают без extern функций, хотя активно использую и пространства имен, и раздельную компиляцию.

Подскажите пожалуйста по сабжу, для чего нужен extern при написании обычных с++ функций?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.10.2025, 12:32
Ответы с готовыми решениями:

Что означает extern "C" или extern "C++"?
Например такой код, extern "C" void f(); Или C++ вместо C. Что это означает и где это применяется...

Не могу разобраться с компоновкой QT
Доборого времени суток. Пишу первую программу с использованием QT (и вторую вообще:)). Не могу...

Какая разница между компиляцией и компоновкой?
только начал учить C++ и возник такой вопрос

20
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
12.10.2025, 12:55
Цитата Сообщение от ADnD Посмотреть сообщение
Мои программы прекрасно работают без extern функций
Они по-умолчанию extern
1
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,519
12.10.2025, 13:13
Цитата Сообщение от ADnD Посмотреть сообщение
для чего нужен extern при написании обычных с++ функций?
Ни для чего не нужен)
"Обычные" функции итак уже по умолчанию имеют external linkage specifier
Поэтому, явное указание external для них никакого нового эффекта уже не окажет.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13200 / 6835 / 1822
Регистрация: 18.10.2014
Сообщений: 17,293
12.10.2025, 23:08
Цитата Сообщение от ADnD Посмотреть сообщение
Разобрался с модульным построением программ (через пространства имен) и раздельной компиляцией, понимаю что в заголовочных файлах нужно объявлять переменные с модификатором extern, а определять их в единственном месте в соответствующем *.cpp файле. Пишу программы в таком стиле и они работают.
"В таком стиле"?

Речь, очевидно, идет о глобальных переменных. Злоупотребление глобальными переменными - это уже серьезная стилистическая проблема, которая к тому же легко может эволюционировать в существенно более серьезные проблемы.

Также, в современном С++ вы можете избежать дублирования объявлений (то есть обойтись без вот этого двойного "объявлять ... с модификатором extern, а определять ... в *.cpp файле") путем единственного объявления-определения в заголовочном файле с ключевым словом inline. Никакого extern не нужно. Никакого "определять в *.cpp файле" тоже не нужно.

Цитата Сообщение от ADnD Посмотреть сообщение
Но не могу понять следующего: для чего и в каких функциях использовать extern при объявлении функции. Тут не веду речь об extern "C", с ним то как раз все ясно.
extern при объявлении функции в С++ не нужен никогда, за исключением этого самого варианта extern "C".

Цитата Сообщение от ADnD Посмотреть сообщение
Мои программы прекрасно работают без extern функций, хотя активно использую и пространства имен, и раздельную компиляцию.
Все обычные функции и так неявно extern, если вы явно не укажете иного. Поэтому явное указание extern не нужно.

Цитата Сообщение от ADnD Посмотреть сообщение
Подскажите пожалуйста по сабжу, для чего нужен extern при написании обычных с++ функций?
Ни для чего не нужен.
1
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6241 / 2954 / 1047
Регистрация: 01.06.2021
Сообщений: 10,979
12.10.2025, 23:51
Цитата Сообщение от TheCalligrapher Посмотреть сообщение
в современном С++ вы можете избежать дублирования объявлений [...] путем единственного объявления-определения в заголовочном файле с ключевым словом inline.
С++17 вполне оптимальная версия для того, чтобы начать проект в 2025, хотя я бы даже С++20 выбрал. Но есть еще те, кто пишет на C++11 или даже на более старых версиях... Хорошо, что вы правильным вещам учите.
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13200 / 6835 / 1822
Регистрация: 18.10.2014
Сообщений: 17,293
13.10.2025, 05:19
Цитата Сообщение от Royal_X Посмотреть сообщение
Но есть еще те, кто пишет на C++11 или даже на более старых версиях...
Многие (если не большинство) новых возможностей С++ - это лишь довольно тонкие оболочки над уже существовавшими ранее возможностями. Умение (точнее, необходимость) вычищать из программы множественные определения одной и той же глобальной сущности (как функций, так и переменных) было привнесено в язык inline-функциями и шаблонами. А когда такое умение уже реализовано, тогда поддержка inline-переменных - это уже фактически просто синтаксический сахар.

С самого начала времен (т.е. с С++98), если вам совсем не хотелось возиться с раздвоенными объявлением и определением глобальной переменной global_variable, у вас была возможность объявить в заголовочном файле

C++
1
2
3
4
5
inline int &global_variable()
{
  static int global_variable_ = 42;
  return global_variable_;
}
и далее просто использовать в программе global_variable() в роли переменной. Это может выглядеть внешне странновато, но достигает требуемого эффекта.

Ясно, что раз компилятор-линкер уже вынуждены решать задачу обеспечения единственности локальной статической global_variable_, то до просто inline-переменных, без необходимости функции-оболочки, остался совсем маленький шаг.
3
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
13.10.2025, 18:42  [ТС]
Всем спасибо за понятные объяснения! Теперь у меня одним сомнением меньше: extern в с++ функциях действительно не нужен!

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
Речь, очевидно, идет о глобальных переменных.
Все переменные объявляю в пространствах имен, глобальные не нужны. Написать data::results ненамного сложнее, чем results. Если каждый раз лень писать "data::", то можно один раз using data::... Не вижу сложностей

Цитата Сообщение от TheCalligrapher Посмотреть сообщение
путем единственного объявления-определения в заголовочном файле с ключевым словом inline.
Есть ли рекомендации, когда не стоит пользоваться модификатором inline?
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
13.10.2025, 18:58
Цитата Сообщение от ADnD Посмотреть сообщение
Есть ли рекомендации, когда не стоит пользоваться модификатором inline?
Во всех случаях, кроме тех, когда нужно.
0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
13.10.2025, 19:56  [ТС]
Не понятен ответ. Из него кажется что inline в общем случае пользоваться не стоит. А использовать только в определенных случаях, так??

Я примерно так думал: inline для маленьких простых функций, замена макросам языка С. Т.е. никаких рекурсий, функций вызываемых по указателям.

Хотелось бы понять, когда на практике использовать inline, а когда не стоит
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6241 / 2954 / 1047
Регистрация: 01.06.2021
Сообщений: 10,979
13.10.2025, 21:20
Цитата Сообщение от ADnD Посмотреть сообщение
Хотелось бы понять, когда на практике использовать inline, а когда не стоит
все случаи не скажу, но современное применение inline сводится к его использованию для функций и статических переменных в заголовочных файлах, чтобы избежать ошибок множественных определений при линковке и чтобы тем самим соблюсти ODR.
Исторически, inline использовался в качестве подсказки компилятору, что нужно вставить тело функции прямо в место вызова, вместо генерации call (типа когда есть маленькая функция, которая часто вызывается). Но современные компиляторы неплохо оптимизируют код в -O2 и выше и не нуждаются в такой порнографии.
А вот не нужно использовать для больших функций, т.к. это приведет к бинарному раздуванию кода. Для виртуальных функций обычно тоже не нужно использовать, т.к. там функции определяются через виртуальные таблицы.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
13.10.2025, 22:38
Цитата Сообщение от Royal_X Посмотреть сообщение
А вот не нужно использовать для больших функций, т.к. это приведет к бинарному раздуванию кода.
То есть?
Если inline это уже не про встраивания а про связывание, то при чем тут размер тела этой функции?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6241 / 2954 / 1047
Регистрация: 01.06.2021
Сообщений: 10,979
13.10.2025, 22:41
Цитата Сообщение от SmallEvil Посмотреть сообщение
Если inline это уже не про встраивания а про связывание, то при чем тут размер тела этой функции?
я писал это в контексте встраивания
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
13.10.2025, 22:50
Цитата Сообщение от Royal_X Посмотреть сообщение
я писал это в контексте встраивания
Из контекста этого совсем не заметно. У ТС может сложится впечатление что это советы по его вопросу.
Так и зачем? Если это потеряло актуальность уже достаточно давно?
Цитата Сообщение от cppreference
Because the meaning of the keyword inline for functions came to mean "multiple definitions are permitted" rather than "inlining is preferred" since C++98
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6241 / 2954 / 1047
Регистрация: 01.06.2021
Сообщений: 10,979
13.10.2025, 22:55
Цитата Сообщение от SmallEvil Посмотреть сообщение
Из контекста этого совсем не заметно.
не из контекста темы, а из контекста моего ответа. Со слова "исторически", там про встраивание...
0
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
14.10.2025, 01:24  [ТС]
Почитал Ваши ответы про inline и запутался еще больше. Если inline теперь не про встраивание, то зачем он вообще нужен? Для чего нужны множественные определения, если достаточно раскидать объявления функций по пространствам имен в заголовочных файлах и сделать по одному определению в соответствующих *.cpp. И все будет четко и понятно, тем более в современных IDE на мониторах с большим разрешением?!
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,519
14.10.2025, 02:13
Цитата Сообщение от ADnD Посмотреть сообщение
Для чего нужны множественные определения
Ни для чего.

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

Например, вы разрабатываете HEADER_ONLY библиотеку, и вам позарез понадобилось специализировать шаблон.
Благодаря inline specifier, вы сможете определить специализацию прям в заголовочном файле:

C++
1
2
3
4
5
6
7
8
9
#ifndef TPL_H
#define TPL_H
template<class T> void f(T) {}
template<class T> inline T g(T) {}
 
template<> inline void f<>(int) {} // OK: inline
 
template<> int g<>(int) {} // error: not inline
#endif
1
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13200 / 6835 / 1822
Регистрация: 18.10.2014
Сообщений: 17,293
14.10.2025, 07:57
Цитата Сообщение от ADnD Посмотреть сообщение
Если inline теперь не про встраивание, то зачем он вообще нужен?
inline нужен для того, чтобы можно было втыкать полное определение глобальной функции в каждый .cpp, но при это не получать ругани от линкера о множественном определении. Это же самое относится и к глобальным переменным.

То есть, выражаясь просто и грубо, назначение inline - это "подавлять" классическое правило ODR, то есть давать вам возможность клепать множественные определения глобальных сущностей (в разных единицах трансляции) и при этот не получать ошибок линкера о множественных определениях. Вместо ругани линкер будет покорно и молча удалять лишние определения из финального кода, оставляя только одно.

Цитата Сообщение от ADnD Посмотреть сообщение
Для чего нужны множественные определения,
Они нужны для того, чтобы в каждом .cpp компилятор мог видеть полное определение тела функции. Тогда (и только тогда!) когда компилятор может видеть полное определение функции, эта функция автоматически становится кандидатом на встраивание. (Неважно, если ли на этой функции inline или нет. Если тело функции видно компилятору - то эта функция является кандидатом на встраивание.)

Если же компилятор не видит полного определения функции в каком-то .cpp, то в этом .cpp он никак не сможет встроить данную функцию, а будет вынужден генерировать обычные вызовы и ждать, что линкер эти вызовы потом правильно разрешит.

Цитата Сообщение от ADnD Посмотреть сообщение
если достаточно раскидать объявления функций по пространствам имен в заголовочных файлах и сделать по одному определению в соответствующих *.cpp.
В такой ситуации компилятор будет видеть тело функции только в одном .cpp - там, где функция определена. И только в этом .cpp функция будет кандидатом на встраивание. В других .cpp встроить ее вызовы будет невозможно.

Таким образом, inline по-прежнему связан с встраиванием вызовов, но косвенно. Он не "запрашивает" встраивание (как было принято интерпретировать его назначение раньше), а лишь создает благоприятные условия для встраивания. А уже встраивать или нет - это компилятор решит сам на основе своих внутренних критериев.

Дополнительно к поддержке встраивания функций, такая роль inline также позволяет вам создавать header-only библиотеки - еще одна ценная возможность inline, которая ценна и для переменных.
1
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
14.10.2025, 20:29  [ТС]
TheCalligrapher, спасибо за понятное объяснение. Можно я Вас еще порасспрашиваю?

Я понимаю, что встраивание повышает быстродействие. Обратной стороной является увеличение кода. Учитывая доступные ресурсы современных вычислительных систем (не считая встраиваемых систем, микроконтроллеров и т.п., но там обычно чистый С или ассемблер) и то что непосредственно код занимает МАЛУЮ долю конечного программного продукта, наверное, целесообразно использовать встраивание максимально широко, насколько возможно. Прав я или нет?

Отсюда вопрос, в каких случаев встраивание использовать не стоит??? Я вижу рекурсивные функции и функции вызываемые по указателям (т.к. на момент компиляции может быть не известно, какая конкретно функция может быть вызвана). Подскажите как оно на самом деле??
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
13200 / 6835 / 1822
Регистрация: 18.10.2014
Сообщений: 17,293
14.10.2025, 21:00
Цитата Сообщение от ADnD Посмотреть сообщение
Отсюда вопрос, в каких случаев встраивание использовать не стоит???
Мне не понятен этот вопрос. "Стоит или не стоит" - это вопрос, который может задавать человек, который пишет свой собственный компилятор/кодогенератор/оптимизатор. Вы пишете свой собственный компилятор?

Если нет, то вопроса "стоит или не стоит" для вас не существует. У вас нет контроля над встраиванием. Решения о встраивании (когда оно возможно) принимает компилятор, на основе своих внутренних критериев. Ваша задача - лишь не мешать ему в этом, по возможности.

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

Например, если вы хотите скрыть реализацию каких-то типов данных и соответствующих функций, то вам придется определять все в .cpp файлах. Это приведет к тому, что соответствующие функции не будут встраиваться. Но такой подход, еще раз, был принят ради важной цели: сокрытия реализации, а встраивание или не встраивание здесь - вопрос десятый.

Если же вы хотите написать header-only библиотеку, то получится наоборот: вся реализация окажется полностью открытой и все функции такой библиотеки будут потенциально встраиваемыми. Но, опять же, это решение было принято не ради встраивания, а ради удобства header-only библиотек. Встраивание здесь сбоку припеку.

И только если у вас нет никаких других доминирующих соображений, диктующих способы определения функций, тогда можно прибегнуть к некоему нечеткому интуитивному делению функций на "большие" и "маленькие". Большие идут в . cpp файл, а маленькие - в . h файл с inline.

Цитата Сообщение от ADnD Посмотреть сообщение
Я вижу рекурсивные функции и функции вызываемые по указателям
Опять же: компилятор принимает решения в таких случаях. Это не ваша забота.

Никто не запрещает компилятору встраивать несколько уровней вложенности рекурсивной функции (или даже все, если он точно знает сколько их будет). Никто не запрещает компилятору встраивать вызов через указатель, если он знает куда этот указатель указывает.
1
1 / 1 / 0
Регистрация: 05.12.2024
Сообщений: 60
15.10.2025, 11:06  [ТС]
TheCalligrapher, как я понял из Вашего ответа, во главу угла ставится вопрос компоновки программы: где разместить тело той или иной функции
1) в заголовочном файле. тогда она inline и кандидат на встраивание.
2) в *.cpp файле. тогда она "обычная" и может встраиваться только при вызове из того же *.cpp где она была объявлена.

Другими соображениями голову можно не забивать. Спасибо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.10.2025, 11:06
Помогаю со студенческими работами здесь

Extern: Есть ли на данный момент набор инструментов, которые позволили бы использовать другие языки
Всем доброго времени суток. Часто встречаю использование оператора (если это, конечно, вообще...

Опишите функцию extern в Си, её аргументы, назначение и что возвращае
Опишите пожалуйста функцию extern в Си, её аргументы, назначение и что возвращает. Не могу найти...

Использование extern с функциями
Добрый вечер! Скажем я задекларировал в каком-то модуле функцию extern void foo() ;. Но не...

Пример использования функции extern
Доброго времени суток форумчане! Пытаюсь закрыть долг по программированию, но препод очень жесткий...

В чем ошибка при объявлении функции, как extern C?
Добрый вечер! В заголовочном файле MemoryManager.h есть ряд объявлений типа: extern &quot;C&quot; void*...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
Архитектура слоя интернета для сервера-слоя.
Hrethgir 11.04.2026
В продолжение https:/ / www. cyberforum. ru/ blogs/ 223907/ 10860. html Знаешь что я подумал? Раз мы все источники пишем в голове ветки, то ничего не мешает добавить в голову такой источник, который сам. . .
Подстановка значения реквизита справочника в табличную часть документа
Maks 10.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача №1: при указании работ (справочник РаботыПоРемонтуСпецтехники),. . .
Очистка реквизитов документа при копировании
Maks 09.04.2026
Алгоритм из решения ниже применим как для типовых, так и для нетиповых документов на самых различных конфигурациях. Задача: при копировании документа очищать определенные реквизиты и табличную. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru