Suppose we have below code:
inline void DoSome()
{
cout << "do some" << endl;
}
int main()
{
void (*pDoSome)() = DoSome;
DoSome(); // one
pDoSome(); // two
}
For above code we have three possible scenarios:
one will be inlined, two won't
one and two will be inlined
one and two won't be inlined (because we took the address of function)
Now I want know which of the above scenarios is true?
inline is a hint to the compiler, but it is not an obligation. It is up to the compiler to decide if a function declared as inline will actually be inlined and thus any of the two calls may or may not be inlined.
All scenarios are possible, because the compiler may optimise as it wants. The only option to see what happened is to look in the assembler output.
Related
The question is in the title but it's not necessarily clear so here's a code example of what I wanted to do:
#include <iostream>
typedef void (*functions)(void);
inline void func_A()
{
std::cout << "I am A !" << std::endl;
}
inline void func_B()
{
std::cout << "I am B !" << std::endl;
}
int main()
{
functions funcs[2] = {func_A, func_B};
for (int i = 0; i < 2; i++)
funcs[i]();
return 0;
}
Is this a good idea compared to the interest of an inline function? Does the compiler handle this well?
Thanks in advance !
You can easily look at the output of the compilers to see how they handle your code. Here my results for current compilers with O2 optimization flags, see https://godbolt.org/z/ecjjz88hs.
Current MSVC seems to not optimize the calls at all. It doesn't even unroll the loop and therefore also doesn't determine which functions are actually indirectly called and also consequently can't inline the function calls.
GCC 12.1 does unroll the loop and turns the indirect function calls into direct function calls, but decides not to inline them.
Clang 14.0.0 does unroll the loop and also does inline the two calls to func_A and func_B.
Note that these results can easily change if you change the details of your example, in particular the number of functions called. It is also non-obvious that inlining the function calls is the best decision here. Compared to the cout << statements the function call overhead is negligible.
The inline keyword on the functions has no impact on these behaviors. The compilers considered above behave exactly the same with or without it.
inline may be a hint to the compiler that the function should be considered for inlining. But that is only a very secondary purpose of the keyword. Compilers will consider non-inline functions for inlining as well and mainly use internal heuristics to decide whether inlining is appropriate or not.
The main purpose of the inline keyword is to be able to define a function in a header file. An inline function definition may (in contrast to a non-inline one) appear in multiple translation units. (In fact an inline function must have its definition appear in any translation unit using that function.) This helps inlining by giving the compiler access to the definition of the function directly in the translation unit using it. Without link-time optimization (LTO) compilers can't really inline function calls across translation units.
If a function is meant to be used in only one translation unit anyway, then it should be marked static, not inline, so that it cannot conflict with other functions of the same name that are meant to be local to another translation unit.
Why should i do something like this:
inline double square (double x) { return x*x;}
instead of
double square (double x) { return x*x;}
Is there a difference?
The former (using inline) allows you to put that function in a header file, where it can be included in multiple source files. Using inline makes the identifier in file scope, much like declaring it static. Without using inline, you would get a multiple symbol definition error from the linker.
Of course, this is in addition to the hint to the compiler that the function should be compiled inline into where it is used (avoiding a function call overhead). The compiler is not required to act upon the inline hint.
On a modern compiler there is likely not much difference. It may be inlined without the inline and it may not be inlined with the inline.
Yes there is a difference. https://isocpp.org/wiki/faq/inline-functions.
When you specify that a function is inline you are causing the compiler to put the code of the method in where ever it is being called.
void myfunc() {
square(2);
}
is identical to
void myfunc() {
2 * 2;
}
Calling a function is good for code clarity, but when that function is called the local state has to be pushed to the stack, a new local state is setup for the method, and when it is done the previous state needs to be popped. That is a lot of overhead.
Now if you up your optimization level, the compiler will make decisions like unrolling loops or inlining functions. The compiler is still free to ignore the inline statement.
From Wikipedia: Inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined. Compilers are not obligated to respect this request.
http://en.wikipedia.org/wiki/Inline_function
inline works well with the concept of procedural abstraction:
inline double square (double x) { return x*x;}
int squareTwice(double x) {
double first = square(x);
double second = square(x);
return first * second;
}
The above is fundamentally similar to the following:
int squareTwice(double x) {
double first = x*x;
double second = x*x;
return first * second;
}
This happens because when the compiler inline-expands a function call, the function's code gets inserted into the caller's code stream; therefore, it may be easier to procedurally abstract the second example to the first example.
Procedural abstraction makes it possible to break up a routine into smaller subroutines that are much easier to read (although this can be a style choice).
The inline function, if the compiler complies, will include the inline function in the code in which it was called as if no function was called (as though you had put the logic in the calling function) and avoid the function call overhead.
This question already has answers here:
When should I write the keyword 'inline' for a function/method?
(16 answers)
Closed 8 years ago.
I was searching the internet a few topics related to inline functions, but none of them took my doubts.
So far I know the inline function works the same way that a method or a block, but recently saw the following response:
By declaring a function inline you tell the compiler to replace the
complete code of that function directly into the place from where it
was called. This is a rather advanced feature that requires
understanding of lower-level programming.
So that means that in normal functions: I was at a point A and wanted to go to point B for that I get out of A and go to B, right?
Have inline functions works in this way: I was at point A and would like to go to point B for that point B comes up to point A?
What I said above is correct?
Ideally, with the inline keyword, the compiler pastes the contents of the inlined function at the point where the function is called.
Given:
void Print(void)
{
cout << "Hello World!\n";
}
int main(void)
{
Print();
return 0;
}
The compiler would emit an assembly instruction to call the Print function inside the main function.
When declaring the Print function as inline, the compiler would generate the conceptual main() function below:
int main(void)
{
// Substitute content of Print function because it's declared as inline
cout << "Hello World!\n";
return 0;
}
Remember that the inline keyword is a suggestion to the compiler and the compiler can ignore it. The compiler may already inline small functions without using the inline keyword.
Long ago, the inline keyword was used to force compilers to paste code where the function was invoked. This technique was used to eliminate function call overhead. This was in the times when compilers were less intelligent about optimizing.
The quote should read "replace the call" ... "place the complete code". The ideal behind an inline function is similar to a macro; in every place in the source code that calls the inline function, instead of calling the inline function, the call is replaced with the complete code from the inline function, and no call is made. This could generate a lot of duplicate code, but should result in faster execution, unless the increase in code size causes issues with cache. In some cases, a compiler may ignore the inline option and use a normal call.
Inline functions is a good tool when you want to save running time because when you call this kind of a function(inline) its code is then written in the call's place. Why does it save time? Because calling a regular function simply consumes more time than just pasting its functionality. Example:
inline void sayHi()
{
std::cout<<"Hi!";
}
int main()
{
sayHi(); //Calling an inline function
std::cin.get();
}
compiler pastes std::cout<<"Hi!"; instead of sayHi();
So what you said is actually correct.
well last time I checked an inline function is a function whose body is substituted directly in every point in the program where the function is called.
So when I do this :
#include <iostream>
inline void increment(int n) { n = n + 1; }`
int main() {
int n = 0;
increment(n);
std::cout << "Result " << n;
}
I should have : Result 1.
Instead, I get 0.
So how does an inline function work ?
'inline' doesn't replace the text with the function body the way a macro does. It replaces the function call with the EQUIVALENT generated code, so that functionaly it's no different than if it weren't inline.
This is not a problem with it being inline but with the method signature being wrong:
inline void increment(int& n) {
++n;
}
You're asking for a copy, you're getting one. Instead ask for a reference. Don't confuse inline functions with macros, they are not the same. In fact, declaring things inline is usually counter-productive as the compiler will make this call for you depending on your optimization settings.
There are two things you should consider while inlining.
1) Inline is just a request to compiler rather than command to replace the function call with its body so as to avoid overhead related to function calls.
2) You should always inline the functions which are pretty small like getters/setters. Because inlining large functions OR recursive functions lead to code bloat which defeats the purpose of inlining.
Also inline functions have static linkage.
Why should i do something like this:
inline double square (double x) { return x*x;}
instead of
double square (double x) { return x*x;}
Is there a difference?
The former (using inline) allows you to put that function in a header file, where it can be included in multiple source files. Using inline makes the identifier in file scope, much like declaring it static. Without using inline, you would get a multiple symbol definition error from the linker.
Of course, this is in addition to the hint to the compiler that the function should be compiled inline into where it is used (avoiding a function call overhead). The compiler is not required to act upon the inline hint.
On a modern compiler there is likely not much difference. It may be inlined without the inline and it may not be inlined with the inline.
Yes there is a difference. https://isocpp.org/wiki/faq/inline-functions.
When you specify that a function is inline you are causing the compiler to put the code of the method in where ever it is being called.
void myfunc() {
square(2);
}
is identical to
void myfunc() {
2 * 2;
}
Calling a function is good for code clarity, but when that function is called the local state has to be pushed to the stack, a new local state is setup for the method, and when it is done the previous state needs to be popped. That is a lot of overhead.
Now if you up your optimization level, the compiler will make decisions like unrolling loops or inlining functions. The compiler is still free to ignore the inline statement.
From Wikipedia: Inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined. Compilers are not obligated to respect this request.
http://en.wikipedia.org/wiki/Inline_function
inline works well with the concept of procedural abstraction:
inline double square (double x) { return x*x;}
int squareTwice(double x) {
double first = square(x);
double second = square(x);
return first * second;
}
The above is fundamentally similar to the following:
int squareTwice(double x) {
double first = x*x;
double second = x*x;
return first * second;
}
This happens because when the compiler inline-expands a function call, the function's code gets inserted into the caller's code stream; therefore, it may be easier to procedurally abstract the second example to the first example.
Procedural abstraction makes it possible to break up a routine into smaller subroutines that are much easier to read (although this can be a style choice).
The inline function, if the compiler complies, will include the inline function in the code in which it was called as if no function was called (as though you had put the logic in the calling function) and avoid the function call overhead.