What is wrong with using inline functions?
It worth pointing out that the inline keyword is actually just a hint to the compiler. The compiler may ignore the inline and simply generate code for the function someplace.
The main drawback to inline functions is that it can increase the size of your executable (depending on the number of instantiations). This can be a problem on some platforms (eg. embedded systems), especially if the function itself is recursive.
I'd also recommend making inline'd functions very small - The speed benefits of inline functions tend to diminish as the function grows in size. At some point the overhead of the function call becomes small compared to the execution of the function body, and the benefit is lost.
When to use inline function and when not to use it?
Avoiding the cost of a function call is only half the story.
do:
- use
inline
instead of#define
- very small functions are good candidates for
inline
: faster code and smaller executables (more chances to stay in the code cache) - the function is small and called very often
don't:
- large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead
- inline functions that are I/O bound
- the function is seldom used
- constructors and destructors: even when empty, the compiler generates code for them
- breaking binary compatibility when developing libraries:
- inline an existing function
- change an inline function or make an inline function non-inline: prior version of the library call the old implementation
when developing a library, in order to make a class extensible in the future you should:
- add non-inline virtual destructor even if the body is empty
- make all constructors non-inline
- write non-inline implementations of the copy constructor and assignment operator unless the class cannot be copied by value
Remember that the inline
keyword is a hint to the compiler: the compiler may decide not to inline a function and it can decide to inline functions that were not marked inline
in the first place. I generally avoid marking function inline
(apart maybe when writing very very small functions).
About performance, the wise approach is (as always) to profile the application, then eventually inline
a set of functions representing a bottleneck.
References:
- To Inline or Not To Inline
- [9] Inline functions
- Policies/Binary Compatibility Issues With C++
- GotW #33: Inline
- Inline Redux
- Effective C++ - Item 33: Use inlining judiciously
EDIT: Bjarne Stroustrup, The C++ Programming Language:
A function can be defined to be
inline
. For example:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
The
inline
specifier is a hint to the compiler that it should attempt to generate code for a call offac()
inline rather than laying down the code for the function once and then calling through the usual function call mechanism. A clever compiler can generate the constant720
for a callfac(6)
. The possibility of mutually recursive inline functions, inline functions that recurse or not depending on input, etc., makes it impossible to guarantee that every call of aninline
function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate720
, another6 * fac(5)
, and yet another an un-inlined callfac(6)
.To make inlining possible in the absence of unusually clever compilation and linking facilities, the definition–and not just the declaration–of an inline function must be in scope (§9.2). An
inline
especifier does not affect the semantics of a function. In particular, an inline function still has a unique address and so hasstatic
variables (§7.1.2) of an inline function.
EDIT2: ISO-IEC 14882-1998, 7.1.2 Function specifiers
A function declaration (8.3.5, 9.3, 11.4) with an
inline
specifier declares an inline function. The inline specifier indicates to the implementation that inline substitution of the function body at the point of call is to be preferred to the usual function call mechanism. An implementation is not required to perform this inline substitution at the point of call; however, even if this inline substitution is omitted, the other rules for inline functions defined by 7.1.2 shall still be respected.
Problems with linking inline functions in C++
//test2.h
#ifndef TEST2_H_INCLUDED
#define TEST2_H_INCLUDED
#include "test1.h"
inline int add(int a,int b) {
return a+b;
}
#endif // TEST2_H_INCLUDED
Some problem about inline function in VS2019
From this One Definition Rule (ODR) reference:
If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the program is ill-formed, no diagnostic required.
[Emphasis mine]
If you have an ODR-violation (which you have since the two definitions are not identical) the compiler doesn't have to emit a warning or error message.
Why can forced inline functions lead to bad performance?
There may be an edge case where inlining a function can increase the program size or move bits of the program around so that cache misses occur where they didn't before. It wouldn't be common, since caches are designed to handle most common situations and are quite large compared to most hotspots.
Is it wrong to place inline functions in C headers?
From n1570 (latest public C11 draft), §6.7.4:
- A function declared with an
inline
function specifier is an inline function. Making a
function an inline function suggests that calls to the function be as fast as possible. The extent to which such suggestions are effective is implementation-defined.
The next section goes into details about linkage, but this passage above is basically all the C standard has to say about inline
. Note how this gives the implementation every freedom, including to completely ignore inline
.
Therefore, with just standard C, you could end up with multiple instances (one per translation unit) of a function that is called in the normal way. This is normally not what you want, as it combines two disadvantages (duplicated code and the overhead of a function call). So I'd argue the standard C inline
is only ever useful for functions private to a single translation unit. Even then, you could assume a good optimizing compiler will automatically pick candidates for inlining, without an explicit inline
.
If on the other hand your compiler provides a way to actually force inlining of a function (which according to your comments, the _inline
specifier does for your compiler), having these functions in a header is safe. But be aware it is in no way portable.
As commented by cmaster, you can achieve kind of "manual inlining" with function-like macros instead for a portable solution.
Why is it not cost effective to inline functions with loops or switch statements?
Inlining functions with conditional branches makes it more difficult for the CPU to accurately predict the branch statements, since each instance of the branch is independent.
If there are several branch statements, successful branch prediction saves a lot more cycles than the cost of calling the function.
Similar logic applies to unrolling loops with switch
statements.
The Google guide referenced doesn't mention anything about functions returning values, so I'm assuming that reference is elsewhere, and requires a different question with an explicit citation.
Related Topics
How Does _Builtin_Clear_Cache Work
A Fast Method to Round a Double to a 32-Bit Int Explained
How to Typically/Always Use Std::Forward Instead of Std::Move
Why Is the Copy-Constructor Argument Const
Math to Convert Seconds Since 1970 into Date and Vice Versa
Overloading Base Class Method in Derived Class
Why Doesn't Std::String Provide Implicit Conversion to Char*
C++ Error: '_Mm_Sin_Ps' Was Not Declared in This Scope
What Does "Memory Allocated at Compile Time" Really Mean
Defining Global Constant in C++
Detailed Guide on Using Gcov with Cmake/Cdash
Compiling with -Static-Libgcc -Static-Libstdc++ Still Results in Dynamic Dependency on Libc.So
How to Export a C++ Class from a Dll
C++: When (And How) Are C++ Global Static Constructors Called