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.
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:
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 of fac()
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 constant 720
for a call fac(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 an inline
function is actually inlined. The degree of cleverness of a compiler cannot be legislated, so one compiler might generate 720
, another 6 * fac(5)
, and yet another an un-inlined call fac(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 has static
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.
Best Answer
Performance
As has been suggested in previous answers, use of the
inline
keyword can make code faster by inlining function calls, often at the expense of increased executables. “Inlining function calls” just means substituting the call to the target function with the actual code of the function, after filling in the arguments accordingly.However, modern compilers are very good at inlining function calls automatically without any prompt from the user when set to high optimisation. Actually, compilers are usually better at determining what calls to inline for speed gain than humans are.
Declaring functions
inline
explicitly for the sake of performance gain is (almost?) always unnecessary!Additionally, compilers can and will ignore the
inline
request if it suits them. Compilers will do this if a call to the function is impossible to inline (i.e. using nontrivial recursion or function pointers) but also if the function is simply too large for a meaningful performance gain.One Definition Rule
However, declaring an inline function using the
inline
keyword has other effects, and may actually be necessary to satisfy the One Definition Rule (ODR): This rule in the C++ standard states that a given symbol may be declared multiple times but may only be defined once. If the link editor (= linker) encounters several identical symbol definitions, it will generate an error.One solution to this problem is to make sure that a compilation unit doesn't export a given symbol by giving it internal linkage by declaring it
static
.However, it's often better to mark a function
inline
instead. This tells the linker to merge all definitions of this function across compilation units into one definition, with one address, and shared function-static variables.As an example, consider the following program:
Note that both
.cpp
files include the header file and thus the function definition ofmean
. Although the file is saved with include guards against double inclusion, this will result in two definitions of the same function, albeit in different compilation units.Now, if you try to link those two compilation units — for example using the following command:
you'll get an error saying “duplicate symbol __Z4meanRKNSt3__16vectorIdNS_9allocatorIdEEEE” (which is the mangled name of our function
mean
).If, however, you uncomment the
inline
modifier in front of the function definition, the code compiles and links correctly.Function templates are a special case: they are always inline, regardless of whether they were declared that way. This doesn’t mean that the compiler will inline calls to them, but they won’t violate ODR. The same is true for member functions that are defined inside a class or struct.