inline

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;
  
}

 

inline

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?

 

Rainer D 6 P2 500x500Modernes C++ Mentoring

  • "Fundamentals for C++ Professionals" (open)
  • "Design Patterns and Architectural Patterns with C++" (open)
  • "C++20: Get the Details" (open)
  • "Concurrency with Modern C++" (open)
  • "Generic Programming (Templates) with C++": October 2024
  • "Embedded Programming with Modern C++": October 2024
  • "Clean Code: Best Practices for Modern C++": March 2025
  • 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,and Matt Godbolt.

    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)

    Do you want to stay informed about my mentoring programs? Subscribe Here

    Rainer Grimm
    Yalovastraße 20
    72108 Rottenburg

    Mobil: +49 176 5506 5086
    Mail: schulung@ModernesCpp.de
    Mentoring: www.ModernesCpp.org

    Modernes C++ Mentoring,

     

     

    0 replies

    Leave a Reply

    Want to join the discussion?
    Feel free to contribute!

    Leave a Reply

    Your email address will not be published. Required fields are marked *