Inline Functions
The inline keyword’s real job is an ODR exemption — it lets a function be defined in a header and included in many translation units — while “inlining” the call is a separate optimizer decision.
Why it matters
Most engineers think inline means “paste the body to avoid a call.” It barely does in modern compilers — the optimizer inlines based on cost heuristics regardless of the keyword, and at -O2 happily inlines functions you never marked. What inline guarantees is linkage: defining a function in a header without it causes “multiple definition” link errors. Since C++17, inline also applies to variables, solving the header-only global problem.
How it works
inlinepermits multiple identical definitions across TUs; the linker merges them into one. All definitions must be token-for-token the same (ODR).- It is a hint, not a command, for actual inline expansion; the compiler may ignore it or inline non-
inlinefunctions. - Functions defined inside a class body are implicitly
inline. constexprfunctions are implicitlyinlinetoo — see constexpr-functions.- Force/forbid expansion with compiler attributes, not the keyword:
gnu::always_inline,__forceinline(MSVC),gnu::noinline.
| Mark | ODR exemption | Forces expansion |
|---|---|---|
inline | yes | no (hint only) |
gnu::always_inline | no | yes (best effort) |
nothing, at -O2 | no | optimizer decides |
Example
// util.hpp — header-only, included everywhere
inline int square(int x) { return x * x; } // OK in N TUs
inline int counter = 0; // C++17 inline variable, one shared instanceDrop the inline on square and include util.hpp in two .cpp files: link fails with multiple definition of square(int).
Pitfalls
- Believing
inlinecontrols performance — measure; the optimizer already inlines hot small calls without it, and over-inlining can hurt via instruction-cache pressure. - ODR mismatch: two TUs with subtly different
inlinebodies (e.g. behind different#defines) is UB the linker won’t catch. - Recursive or large functions can’t be expanded usefully; the keyword is then pure linkage.
- Marking everything
gnu::always_inlinebloats code size and can slow the program down.