У меня тут возник один вопрос, на который из моих знакомы уверенно так никто и не ответил...
Если объявить функцию inline в хедере, а реалезовать ее в cpp файле, будет ли функции после компиляции inline или компилятор сделает ее static?
Вопрос возник из таких размышлений, допустим у меня есть три файла:
finline.h
---------------
inline int f();
finline.cpp
---------------
#include "finline.h"
inline int f()
{
return <чего не будь>;
}
main.cpp
---------------
#include "finline.h"
int a = f();
inline функция прямой подстановки, допустим finline.cpp скомпилировался в объектник первым, при компиляции main.cpp компилятор подставит finline.h в main.cpp и скомпилирует main.obj. Но дело в том, что тело f() находится в finline.cpp, который уже скомпилирован и соотведственно по логике вещей никакой подстановки произойти не должо и линкер просто должен подставить адрес f() при линковке. Из этого следует вопрос inline должна быть полностью реализованна в хедере?
Rockoos пишет:
> У меня тут возник один вопрос, на который из моих знакомы уверенно так > никто и не ответил... > > Если объявить функцию inline в хедере, а реалезовать ее в cpp файле, > будет ли функции после компиляции inline или компилятор сделает ее static? >
Будет. Другой вопрос — что вы имеете в виду под
"функция будет inline". Я — что это функция, у которой есть модификатор inline.
> Вопрос возник из таких размышлений, допустим у меня есть три файла:
> inline функция прямой подстановки, допустим finline.cpp скомпилировался > в объектник первым, при компиляции main.cpp компилятор подставит > finline.h в main.cpp и скомпилирует main.obj. Но дело в том, что тело > f() находится в finline.cpp, который уже скомпилирован и соотведственно > по логике вещей никакой подстановки произойти не должо и линкер просто > должен подставить адрес f() при линковке.
я что-то не понимаю. Если по вашей версии inline -функция — это функция
прямой подстановки, то при чем тут вообще линкер ?
До линкера функция дойти не должна уже, если она подставляется.
Тело компилятор подставляет (ну хотя бы как правило).
Из этого следует вопрос inline > должна быть полностью реализованна в хедере?
Не обязательно, почему же ? Вот в том модуле, где она
определена, она будет как inline и возможно будет подставлена.
Если не подставлена, она не будет помещена в словарь глобальных
имен.
А в том модуле, где она не определена, ссылка на неё будет
сгенерена, и она потом в процессе линковки должна будет
разрешена линкером из словаря глобальных имён. Другое
дело, что вероятнее всего она там не будет найдена
линкером. Но это уже — дело десятое.
А, вы там написали, что она уже в хедере как inline описана...
Ну тогда она просто должна не найтись в каждом модуле,
использующем этот заголовок (и вызывающем функцию, естественно).
И все.
Здравствуйте, Rockoos, Вы писали:
R>Всем привет!
R>У меня тут возник один вопрос, на который из моих знакомы уверенно так никто и не ответил...
R>Если объявить функцию inline в хедере, а реалезовать ее в cpp файле, будет ли функции после компиляции inline или компилятор сделает ее static?
может будет инлайн, может нет. Более того, даже если в .h объявить inline ответ будет такой же. Если компилятор не смог заинлайнить (замечу это делается иногда во время линковки), то он сажает каждое тело в свой коммунальный сегмент, и, после линковки, получается одно тело для ф-ии.
Здравствуйте, Rockoos, Вы писали:
R>...inline должна быть полностью реализованна в хедере?
Да
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Erop пишет: > R>...inline должна быть полностью реализованна в хедере? > > Да
Чего за ерунду -то пишите ?
Если "ДА", то " для того, чтобы во всех модулях
компиляции функция, объявленная как inline, имела
шанс быть за-inline-ной, как правило, для большинства
современных компиляторов требуется, чтобы она была
бы определена в заголовочном файле вместе со своим объявлением
(ну или раздельно)."
СМ>Erop, я от тебя такого не ожидал
Я всего лишь ответил на заданный вопрос. Я вообще, обычно в С++ отвечаю с целью помочь людям, не знающим чего-то в нашем запутанном языке
Я всё ещё думаю, что ответил адекватно и достаточно полно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Сергей Мухин, Вы писали:
СМ>>Erop, я от тебя такого не ожидал E>Я всего лишь ответил на заданный вопрос. Я вообще, обычно в С++ отвечаю с целью помочь людям, не знающим чего-то в нашем запутанном языке
E>Я всё ещё думаю, что ответил адекватно и достаточно полно
1. по крайней мере MSDEV делает inline некоторые ф-ии которые реализованы не в header
2. я думаю можно привести ф-ию с телом в header которая не будет развернута в inline
Здравствуйте, Сергей Мухин, Вы писали:
СМ>1. по крайней мере MSDEV делает inline некоторые ф-ии которые реализованы не в header СМ>2. я думаю можно привести ф-ию с телом в header которая не будет развернута в inline
Видимо тебе интересен более полный ответ, чем топикстартеру.
IMHO он таков.
Когда-то давно, когда компиляторы ещё не были так продвинуты как сейчас, им тербовались подсказки со стороны программиста, чтобы лучше оптимизировать программу.
Примером такой подсказки является слово register.
Слово inline имеет в чём-то похожую судьбу. Когда-то давно слово inline обозначало инструкцию компилятору попробовать использовать знание определения функции в точке её вызова. Например, просто "подставив" код функции в место вызова, или ещё как-то.
При этом, для того, чтобы эта оптимизация была действительно полезной, для inline функций несколько ослабили проверку ODR. То есть определение iline функции могло быть в нескольких единицах трансляции, но при этом все определения должны были совпадать и быть эквивалентны. Это чем-то похоже на определения классов, например.
Как компиляторы и линкеры выкручивались из таких неудобных условий -- вопрос отдельный. Одни, например, помещали определения inline функциий не во все единицы трансляции (вернее не во все объектники), а только в некоторые, выбираемые по каким-нибудь эвристикам. Другие помечали попавшее в объектник определение inline функции, как блок кода, который может быть сдублирован в другом объектнике, и т. д.
Короче говоря выкручивались и выкручиваются, оставляя заботу о совпадении и эквивалентности определений inline функции доступных из разных единиц трансляции на совести программиста. Это, кстати, небезопасно, так как черевато всякими уродскими проблемами.
Например, в одной единице трансляции мы можем написать что-то вроде
ну и нарваться на то, что если ~TableEntry не подставится, и вызовется из "неродной" единицы трансляции, то программа будет совершенно мистически падать при отгрузке.
Возможны и более тонкие эффекты, конечно.
Теперь, после экскурса в историю слова inline и обзора особенностей его относительно честной реализации, можно перейти к сегодняшнему дню. Хотя бывали и бесчестные реализации, конечно. Например такие:
#define inline static
Сегодня любой нормальный компилятор, и многие линкеры тоже, используют в точке вызова информацию о теле всех функций до определения которых они могут добраться. Так что единственный существенный смысл слова inline, который остался -- это ослабление проверки ODR для inline функций.
В этом смысле больше нет смысла писать про функцию inline, и не публиковать в хедере её определение. Хотя, конечно, именно подстановку функции в месте вызова слово inline как не гарантировало, так и не гарантирует Так что на менее глубоком уровне понимания всех этих не особо нужных подробностей, простое утверждение, что опроеделение inline функции всегда следует размещать в хедере совсем и не плохо
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, _Dinosaur, Вы писали:
_D>адекватно — да, достаточно полно — нет
У любого вопроса есть автор и уровень. Уровень часто читается из вопроса, автор может уточнить или переспросить
_D>[ccode]
_D> call f # f(); _D> call e _D> addl $4, %esp _D> movl $35, %eax # g(); _D> popl %ecx _D> popl %ebp _D> leal -4(%ecx), %esp _D> ret _D>[/code]
_D>тут еще генератора кода MSVC не хватает... _D>)
Ну это ничего не доказывает, вообще-то
1) Сейчас компиляторы умеют делать inline-подстановки на этапе линковки. Так что есть вполне реальный расклад, когда твоя main сократится до кода, эквивалентного
return 12;
2) Никто из них (компиляторов) не гарантирует, что какая-то конкретная подстановка будет сделана.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>У любого вопроса есть автор и уровень. Уровень часто читается из вопроса, автор может уточнить или переспросить
+1
[] E>Ну это ничего не доказывает, вообще-т
? E>1) Сейчас компиляторы умеют делать inline-подстановки на этапе линковки.
Кстати, хотел бы взглянуть на генерируемый ими код... E>Так что есть вполне реальный расклад, когда твоя main сократится до кода, эквивалентного
return 12;
вроде так
return 35;
Завидую людям, которые могут себе позволить никуда не спешить.
Здравствуйте, Rockoos, Вы писали:
R>finline.h R>--------------- R>inline int f();
R>finline.cpp R>--------------- R>#include "finline.h" R>inline int f() R>{ R> return <чего не будь>; R>}
R>main.cpp R>--------------- R>#include "finline.h" R>int a = f();
R>inline функция прямой подстановки, допустим finline.cpp скомпилировался в объектник первым, при компиляции main.cpp компилятор подставит finline.h в main.cpp и скомпилирует main.obj. Но дело в том, что тело f() находится в finline.cpp, который уже скомпилирован и соотведственно по логике вещей никакой подстановки произойти не должо и линкер просто должен подставить адрес f() при линковке. Из этого следует вопрос inline должна быть полностью реализованна в хедере?
Всё по порядку.
Для современных компиляторов по-умолчанию не важен порядок компиляции cpp файлов, т.к. всю работу с подстановкой они делают до стадии линковки. При этом есть в некоторых компиляторах режим в котором часть работы компилятора ложиться на компоновщик, но эту тему пока мы оставим.
Далее, если функция f() имеет тело и в finline.cpp/.o и в main.cpp/.o, то адреса у них не обязаны совпадать. Если только вы не пытаетесь её экспортировать (ключевое слово extern), что значит, что функция будет подлинкована на стадии компоновки, т.к. станет "видна" другим модулям, код в которых её вызывает. По умолчанию, каждое объявление функции считается её экспортом, до тех пор пока в том же модуле компилятор не "встретит" её тело. Далее, вы указываете ключевое слово inline на теле функции (кстати на объявлении функции модификатор inline не имеет силы), указывая что вы желаете, чтобы компилятор вставил тело функции в модуль где этот inline приставлен к функции, что возможно и происходит, а может и нет, т.к. inline — это "совет" компилятору, а не "команда".
Далее, у меня получилось юзать такую штуку как extern+inline (extern в паре с inline на теле функции), т.е. использования одновременно и экспортирования и подстановки, что говорит о том что inline функция обычно "реализуется" в хедере, но с этой конструкцией вроде как и не обязана.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Rockoos, Вы писали:
R>Всем громадное спасибо!
Для "спасибо" тут есть кнопки
А так, пожалуйста. Обращайся
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Vain, Вы писали:
V>у меня получилось юзать такую штуку как extern+inline (extern в паре с inline на теле функции)
У меня тоже получалось... в некоторых случаях Internal Compiler Error
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
MZ>А в том модуле, где она не определена, ссылка на неё будет MZ>сгенерена, и она потом в процессе линковки должна будет MZ>разрешена линкером из словаря глобальных имён. Другое MZ>дело, что вероятнее всего она там не будет найдена MZ>линкером.
Точно не будет, inline в частности несет на себе всю семантику static, и функция не глобал.
Я бы не стал вообще такой код писать. И, скорее всего, компиляция обломится, ибо функция не имеет тела при компиляции второго файла.
Здравствуйте, Maxim S. Shatskih, Вы писали:
MSS>Точно не будет, inline в частности несет на себе всю семантику static, и функция не глобал.
1) Это не правда. Связанность функции и то, что она помечена, как inline никак не связано.
Например такой код
// 1.hinline int getCount()
{
static int seed = 0;
return ++seed;
}
// 1.cppconst int id1 = getCount();
// 2.cppconst int id2 = getCount();
валиден, за исключением того, что не известно какие значения получит id1 и id2. Известно только, что разные...
2) Вообще-то нет гарантий, что при помещении определения inline функции в cpp из другой единицы трансляции нельзя будет сослаться на это определение. Многие реализации позволяют так делать. Мало того, некоторые даже смогут выполнить inline подстановку в таких условиях
MSS>Я бы не стал вообще такой код писать. И, скорее всего, компиляция обломится, ибо функция не имеет тела при компиляции второго файла.
Я бы тоже, но совсем по другой причине
. На совреенных компиляторах нет никакого смысла указывать, что функция inline, если нет нужды публиковать её определение для нескольких единиц трансляции
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Rockoos, Вы писали:
R>Из этого следует вопрос inline должна быть полностью реализованна в хедере?
Inline-функция должна быть определена в каждой единице трансляции, в которой она используется, причем все ее определения должны совпадать. Самый простой способ выполнить это требование — определять inline-функцию в том же заголовочном файле, в котором она объявляется.
PS. При компиляции твоего примера, а именно при компиляции main.cpp компилятор должен выдать сообщение об ошибке; впрочем не удивлюсь, если он этого не сделает.