If I define a non-member function in a header, will it always be inlined by the compiler, or does the compiler choose based on its heuristics? I know that __inline is just a hint, is it the same with functions in headers?
It will choose based on heuristics. Make sure you declare it as inline explicitly otherwise you may get a duplicate symbol link error if you include the header in more than one compilation unit.
Remember that including something from a header is no different than just typing it directly in the source file. So being in a header makes no difference as far as the compiler is concerned; it never knew it was there.
So when you define a function in a header file, and you include that header file in a file, it's like you just typed the function straight into the file. So now the question is, "does the compiler choose to inline things based on heuristics?"
The answer is "it depends on the compiler". The standard makes no guarantees about what gets inlined or not. That said, any modern compiler will be extremely intelligent about what it inlines, likely with heuristics.
However, we come to an interesting point. Imagine you have a function in a header and you include that header in multiple source files. You will then have multiple definitions of the function, across translation units, and this violates the one-definition rule. Ergo, you will get compile errors. (The linker error is usually something along the lines of: "Error, function x already defined in y") What you can do is use the inline
keyword and you no longer violate the ODR.
By the way __inline
is non-standard. Contrary to your post, it's usually a compiler extension which forces inlining, not hints it. inline
is the standard keyword, which was originally intended to hint at inlining. Like you say, most modern compilers completely ignore it in that regard and it's only purpose nowadays is to give things internal linkage.
From the C++ FAQ Lite:
No matter how you designate a function as inline, it is a request that the compiler is allowed to ignore: it might inline-expand some, all, or none of the calls to an inline function.
If you define a function with external linkage in a header file and include it into more than one translation unit, you'll get compilation error (more precisely: linker erorr) for violation of One Definition Rule (ODR). So the answer is "no": defining a function in a header file will not be taken by compiler as a hint at inlining and will not excuse you from observing the requirements of ODR. Not only such functions are not guaranteed to be inlined, but most likely your program will not even compile.
In order to define a function in a header file and get away with it you have to either give it internal linkage (declare it static
, and end up with separate function in each translation unit), or explicitly declare it inline
.
As for the heuristics... Modern compilers will normally consider virtually any function for inlining (by applying heuristics), regardless of where it is defined and whether it is explicitly declared inline
or not.
There is no magic about functions in headers. The compiler doesn't even know whether a function is defined in a header or not. (Since headers are effectively just copy/pasted into the source file, you might define it in a header, but the compiler just sees it as part of the translation unit)
There are also two different meanings of "inline" to be aware :
A function may be inlined as defined by the C++ standard: This is done either by prefixing the function with the inline
keyword, or if it is a member function, by defining it in-place inside the class definition.
The effect of this is to
- inform the linker that it may encounter the function definition in multiple files, and it should just silently merge them together instead of throwing an error
- make it easier for the compiler to perform the inlining optimization.
The inlining optimization on the other hand, is simply the act of replacing a function call by the body of the called function, which means that this optimization is actually applied to call sites, not to functions. A function might be called normally some places, but inlined elsewhere. A function call is inlined when the compiler feels like it, and it is best to conceptually separate it entirely from the first meaning of "inline".
The compiler will apply the inlining optimization if, when and where it feels like it. It uses a lot of heuristics for this. Smaller functions are more likely to be inlined. If it determines that a specific call site is going to be executed sufficiently often, it is more likely to be inlined. Ultimately, the heuristics it uses are based on "will it improve or degrade performance". And it is generally a better judge of this than human beings, so you shouldn't really need to know what precise heuristics it uses. Inlining too much will only harm performance.