inline
Thanks to inline, the compiler can replace the function call with the function body. There are two reasons to use inline functions: performance and safety.
My primary goal was to write this post about performance. Fortunately, a further significant benefit of inline came to my mind. inline makes macros a function replacement superfluous.
Macro must go
Macros are only the poor man’s means to replace text. Macros have no understanding of the C++ syntax. Therefore, a lot can go wrong.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// macro.cpp #include <iostream> #define absMacro(i) ( (i) >= 0 ? (i) : -(i) ) inline int absFunction(int i){ return i >= 0 ? i : -i; } int func(){ std::cout << "func called" << std::endl; return 0; } int main(){ std::cout << std::endl; auto i(0); auto res = absMacro(++i); std::cout << "res: " << res << std::endl; absMacro(func()); std::cout << std::endl; i=0; res= absFunction(++i); std::cout << "res: " << res << std::endl; absFunction(func()); std::cout << std::endl; } |
The macro in line 5, as the inline function in lines 7 – 9, returns the absolute value of its arguments. I invoke the function with the argument ++i. i is 0. The result should be 1. It should be because the macro increments the expression i two times. Consequently, the result is 2 instead of 1. The function func shows it explicitly. When I use the function func as an argument, the function will be invoked two times in the case of the macro but only once in the case of the inline function.
What’s happening if I use an inline function?
Modernes C++ Mentoring
Do you want to stay informed: Subscribe.
inline
At first, all behave not as it seems. The compiler will interpret it only as a recommendation if I declare a function as inline. The compiler is free to ignore my recommendation. But it will also work the other way around. Modern compilers like Microsoft Visual C++, gcc, or clang can inline a function if it makes sense from a performance perspective.
Now I have to write in the conjunctive. We must assume the compiler will accept my recommendation and apply the inline keyword in the exchange function.
inline void exchange(int& x, int& y){ int temp= x; x= y; y= temp; }
What’s happening at the function invocation?
... auto a(2011); auto b(2014); exchange(a,b); ...
The compiler substitutes the function call by the function body.
... auto a(2011); auto b(2014); int temp= a; a= b; b= temp; ...
The small example shows the advantages and disadvantages of inline a function.
Advantages
- No function call is necessary.
- Variables have not to be pushed onto or removed from the function stack.
- The function needs no return value.
- The instruction cache can be used optimally. New instructions don’t have to be loaded but can be immediately performed.
Disadvantages
- The size of the executable grows.
Although I only mentioned one disadvantage that should not be judged. The usage of the keyword inline is a balance between performance versus the size of the executable. That was the simple rule. The details are a lot more complicated. Using inline, the executable may become faster or slower, bigger or smaller. inline can cause or prevent the crash of your program. inline case increases or decreases the number of cache misses of your program. Those who want to be confused should read the FAQ about inline functions at isocpp.org.
Until this point, I only wrote about functions. Of course, you can also declare methods as inline.
inline methods
A method can become implicitly and explicitly inline implicitly if you define the method in the class body explicitly if you define the methods outside the class body and use the keyword inline.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// inline.cpp class MyClass{ public: void implicitInline(){}; void explicitInline(); inline void notInline(); }; inline void MyClass::explicitInline(){} void MyClass::notInline(){} int main(){ MyClass cl; cl.implicitInline(); cl.explicitInline(); cl.notInline(); } |
Therefore, the method implicitInline (line 5) is inline because I defined it in the class boy. Therefore, the method explicitInline (line 6) is inline because I used the keyword inline at the point of the method definition. I want to stress one point. If I use only the keyword inline at the point of the method declaration, I will not get an inline function. This error happened to me with the method notInline (line 7).
General recommendation
Good advice is expensive. Should you use the keyword inline ever or never? Of course, the answer is not so simple. You should use inline if you have a function that is time critical and you invoke this function not too often. In this case, the performance advantages will dominate the size disadvantages.
But we have to keep the big picture in our mind. The Working Group WG 21 wrote the paper ISO/IEC TR 18015 about C++ performance in 2006. Chapter 5.3.4 of the paper explicitly discusses the keyword inline on five popular C++ compilers. They compare in this chapter functions, inline functions, and macros. The conclusion in the paper is that inline function calls are about 2-17 times faster than function calls and that inline function calls and macros are in the same performance range.
If this rule of thumb is too simple for you, you should measure the performance of your program. This is, in particular, true for embedded systems that have more substantial resource concerns.
After getting much attention at Reddit for missing the main point about inline functions I will add a few words about ODR.
ODR
ODR stands for the One Definition Rule and says in the case of a function.
- A function can have not more than one definition in any translation unit.
- A function can have not more than one definition in the program.
- Inline functions with external linkage can be defined in more than one translation. The definitions must satisfy the requirement that each must be the same.
In modern compilers, the keyword inline is not about inlining functions anymore. Modern compilers almost completely ignore it. The more or less use-case for inline is to mark functions for ODR correctness. In my opinion, the name inline is nowadays quite misleading.
C versus C++
Sorry, the confusion will not end here. I want to stress that point explicitly.inline function by default has external linkage in C++. This is different from C. In C, inline functions, by default, have internal linkage. You can read the details in the article Linkage of inline functions.
What’s next?
This was a post about classical C++. In the next post, I will write about C++11. C++11 has the keyword constexpr. You can use constexpr for values, functions, and user-defined data types. By constexpr declared constant expression can be evaluated at compile time. They offer a lot of benefits. Which? You will see it in the next post.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Stephen Kelley, Kyle Dean, Tusar Palauri, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, Ann Shatoff, Rob North, Bhavith C Achar, Marco Parri Empoli, Philipp Lenk, Charles-Jianye Chen, Keith Jeffery, Matt Godbolt, and Honey Sukesan.
Thanks, in particular, to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, Slavko Radman, and David Poole.
My special thanks to Embarcadero | |
My special thanks to PVS-Studio | |
My special thanks to Tipi.build | |
My special thanks to Take Up Code | |
My special thanks to SHAVEDYAKS |
Modernes C++ GmbH
Modernes C++ Mentoring (English)
Rainer Grimm
Yalovastraße 20
72108 Rottenburg
Mail: schulung@ModernesCpp.de
Mentoring: www.ModernesCpp.org
Modernes C++ Mentoring,
Leave a Reply
Want to join the discussion?Feel free to contribute!