Should one never use static inline function?
Your analysis is correct, but doesn't necessarily imply uselessness. Even if most compilers do automatically inline functions (reason #1), it's best to declare inline
just to describe intent.
Disregarding interaction with inline
, static
functions should be used sparingly. The static
modifier at namespace scope was formerly deprecated in favor of unnamed namespaces (C++03 §D.2). For some obscure reason that I can't recall it was removed from deprecation in C++11 but you should seldom need it.
So, Practically marking a function static and inline both has no use at all. Either it should be static(not most preferred) or inline(most preferred),
There's no notion of preference. static
implies that different functions with the same signature may exist in different .cpp
files (translation units). inline
without static
means that it's OK for different translation units to define the same function with identical definitions.
What is preferred is to use an unnamed namespace instead of static
:
namespace {
inline void better(); // give the function a unique name
}
static inline void worse(); // kludge the linker to allowing duplicates
static inline vs inline static
From the C standard (6.7 Declarations)
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declaration
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
It means that you may specify declaration specifiers in any order.
So for example all shown below function declarations declare the same one function.
#include <stdio.h>
static inline int getAreaIndex( void );
inline static int getAreaIndex( void );
int static inline getAreaIndex( void );
static int inline getAreaIndex( void );
inline int static getAreaIndex( void )
{
return 0;
}
int main(void)
{
return 0;
}
As for the inline function specifier then according to the C Standard (6.7.4 Function specifiers)
6 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.138)The extent to which such
suggestions are effective is implementation-defined.
and there is a footnote
139) For example, an implementation might never perform inline
substitution, or might only perform inline substitutions to calls in
the scope of an inline declaration
Pay attention to that you should specify as the function parameter void
. Otherwise the compiler will decide that the number and types of arguments are deduced from a function call.
When to use static inline instead of regular functions
Inlining is done for optimization. However, a little known fact is that inline
can also hurt performance: Your CPU has an instruction cache with a fixed size, and inlining has the downside of replicating the function at several places, which makes the instruction cache less efficient.
So, from a performance point of view, it's generally not advisable to declare functions inline
unless they are so short that their call is more expensive than their execution.
To put this in relation: a function call takes somewhere between 10 to 30 cycles of CPU time (depending on the amount of arguments). Arithmetic operations generally take a single cycle, however, memory loads from first level cache takes something like three to four cycles. So, if your function is more complex than a simple sequence of at most three memory accesses and some arithmetic, there is little point in inlining it.
I usually take this approach:
If a function is as simple as incrementing a single counter, and if it is used all over the place, I inline it. Examples of this are rare, but one valid case is reference counting.
If a function is used only within a single file, I declare it as
static
, notinline
. This has the effect that the compiler can see when such a function is used precisely one time. And if it sees that, it will very likely inline it, no matter how complex it is, since it can prove that there is no downside of inlining.All other functions are neither
static
norinline
.
The example in your question is a borderline example: It contains a function call, thus it seems to be too complex for inlining at first sight.
However, the memcpy()
function is special: it is seen more as a part of the language than as a library function. Most compilers will inline it, and optimize it heavily when the size is a small compile time constant, which is the case in the code in question.
With that optimization, the function is indeed reduced to a short, simple sequence. I cannot say whether it touches a lot of memory because I don't know the structure that is copied. If that structure is small, adding the inline
keyword seems to be a good idea in this case.
When to use the 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.
Usage of static inline to functions which calls other larger functions in C
It does not matter. The function total
will not be probably inlined (normal function call will be emitted). Function res
probably will be inlined.
Why probably. Because the inline
keyword is only a suggestion. Functions without inline may be inlined as well. The compiler may inline the total
function as well if decides that on a certain level of optimization it will result in the best code generation.
Many compilers have special extensions which give you control over inlining. for example:
gcc has __attribute__((noinline))
and __attribute__((always_inline))
.
iar #pragma inline=never
and pragma inline=force
Should I define static inline methods in header file?
How to add a function definition in header file?
This can be achieved in 3 possible ways:
- Marking the function
inline
or - Making the function
static
or - Putting the functions in anonymous namespace.
What is the correct way to do so?
#1
i.e: Marking the function inline
is the correct way to this without breaking the One Definition Rule.
What is wrong with the other two appraoches?
In both #2
& #3
each Translation Unit will contain it's own version of the function, and the program will contain several different versions of the function thus leading to a increase in size of the generated binary.
i.e: For a static
function fun()
, &fun
will be different in each translation unit, and the program will contain N
different versions of the function.
Also, If the function contains static local variables then there will be N
different static local variables, one for each function instance.
How the first approach avoids this problem?
An inline
function has external linkage.
When you mark a function inline
the function will have the same address in all translation units. Also, Static locals and string literals defined within the body of an inline function are treated as the same object across translation units.
In short, a inline function will have the same address across all translation units.
What is the deal with
static inline
function definitions in header?
The static
keyword forces the function to have a internal linkage.
Each instance of function defined as inline is treated as a separate function and each instance has its own copy of static locals and string literals. Thus, this would be similar to #2
.
Note:
The standard mandates that all definitions of inline
function in an user program You must have the exact same definition in all translation units in which the function is used or called.
Relevant Standerdese references:
C++03 Standard
3.2 One definition rule:
Para 3:
Every program shall contain exactly one definition of every non-inline function or object that is used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is used.
7.1.2 Function specifiers
Para 4:
An inline function shall be defined in every translation unit in which it is used and shall have exactly the same definition in every case (3.2). [Note: a call to the inline function may be encountered before its definition appears in the translation unit. ] If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. An inline function with external linkage shall have the same address in all translation units. A static local variable in anextern inline function always refers to the same object. A string literal in an extern inline function is the same object in different translation units.
Related Topics
How to Remove Straight Lines or Non-Curvical Lines in a Canny Image
Why Does Int8_T and User Input via Cin Shows Strange Result
Class Members and Explicit Stack/Heap Allocation
Difference Between Std::Function<> and a Standard Function Pointer
Svm Classifier Based on Hog Features for "Object Detection" in Opencv
Creating JSON Arrays in Boost Using Property Trees
How Does the Main() Method Work in C
Why Do Two Functions Have the Same Address
C++ - Std::Thread Crashes Upon Execution
Optimizing Member Variable Order in C++
C++11: Replace All Non-Owning Raw Pointers with Std::Shared_Ptr()
Borderless Window with Drop Shadow
Alpha Rendering Difference Between Opengl and Webgl
Why "Not All Control Paths Return a Value" Is Warning and Not an Error