Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Benefits of inline functions in C++?

People also ask

Why do we use inline function in C?

An inline function is one for which the compiler copies the code from the function definition directly into the code of the calling function rather than creating a separate set of instructions in memory. This eliminates call-linkage overhead and can expose significant optimization opportunities.

Why inline functions are faster?

Inline functions are faster because you don't need to push and pop things on/off the stack like parameters and the return address; however, it does make your binary slightly larger.

What is the need of inline function in programming?

In C++, we can declare a function as inline. This copies the function to the location of the function call in compile-time and may make the program execution faster.

Does inline improve performance?

Inline functions behave like macros. When an inline function gets called, instead of transferring the control to the function, the call gets substituted with the function code. Thus this saves time and improves performance.


Advantages

  • By inlining your code where it is needed, your program will spend less time in the function call and return parts. It is supposed to make your code go faster, even as it goes larger (see below). Inlining trivial accessors could be an example of effective inlining.
  • By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining)

Disadvantages

  • It can make your code larger (i.e. if you use inline for non-trivial functions). As such, it could provoke paging and defeat optimizations from the compiler.
  • It slightly breaks your encapsulation because it exposes the internal of your object processing (but then, every "private" member would, too). This means you must not use inlining in a PImpl pattern.
  • It slightly breaks your encapsulation 2: C++ inlining is resolved at compile time. Which means that should you change the code of the inlined function, you would need to recompile all the code using it to be sure it will be updated (for the same reason, I avoid default values for function parameters)
  • When used in a header, it makes your header file larger, and thus, will dilute interesting informations (like the list of a class methods) with code the user don't care about (this is the reason that I declare inlined functions inside a class, but will define it in an header after the class body, and never inside the class body).

Inlining Magic

  • The compiler may or may not inline the functions you marked as inline; it may also decide to inline functions not marked as inline at compilation or linking time.
  • Inline works like a copy/paste controlled by the compiler, which is quite different from a pre-processor macro: The macro will be forcibly inlined, will pollute all the namespaces and code, won't be easily debuggable, and will be done even if the compiler would have ruled it as inefficient.
  • Every method of a class defined inside the body of the class itself is considered as "inlined" (even if the compiler can still decide to not inline it
  • Virtual methods are not supposed to be inlinable. Still, sometimes, when the compiler can know for sure the type of the object (i.e. the object was declared and constructed inside the same function body), even a virtual function will be inlined because the compiler knows exactly the type of the object.
  • Template methods/functions are not always inlined (their presence in an header will not make them automatically inline).
  • The next step after "inline" is template metaprograming . I.e. By "inlining" your code at compile time, sometimes, the compiler can deduce the final result of a function... So a complex algorithm can sometimes be reduced to a kind of return 42 ; statement. This is for me extreme inlining. It happens rarely in real life, it makes compilation time longer, will not bloat your code, and will make your code faster. But like the grail, don't try to apply it everywhere because most processing cannot be resolved this way... Still, this is cool anyway...
    :-p

Inline functions are faster because you don't need to push and pop things on/off the stack like parameters and the return address; however, it does make your binary slightly larger.

Does it make a significant difference? Not noticeably enough on modern hardware for most. But it can make a difference, which is enough for some people.

Marking something inline does not give you a guarantee that it will be inline. It's just a suggestion to the compiler. Sometimes it's not possible such as when you have a virtual function, or when there is recursion involved. And sometimes the compiler just chooses not to use it.

I could see a situation like this making a detectable difference:

inline int aplusb_pow2(int a, int b) {
  return (a + b)*(a + b) ;
}

for(int a = 0; a < 900000; ++a)
    for(int b = 0; b < 900000; ++b)
        aplusb_pow2(a, b);

In archaic C and C++, inline is like register: a suggestion (nothing more than a suggestion) to the compiler about a possible optimization.

In modern C++, inline tells the linker that, if multiple definitions (not declarations) are found in different translation units, they are all the same, and the linker can freely keep one and discard all the other ones.

inline is mandatory if a function (no matter how complex or "linear") is defined in a header file, to allow multiple sources to include it without getting a "multiple definition" error by the linker.

Member functions defined inside a class are "inline" by default, as are template functions (in contrast to global functions).

//fileA.h
inline void afunc()
{ std::cout << "this is afunc" << std::endl; }

//file1.cpp
#include "fileA.h"
void acall()
{ afunc(); }

//main.cpp
#include "fileA.h"
void acall();

int main()
{ 
   afunc(); 
   acall();
}

//output
this is afunc
this is afunc

Note the inclusion of fileA.h into two .cpp files, resulting in two instances of afunc(). The linker will discard one of them. If no inline is specified, the linker will complain.


Inlining is a suggestion to the compiler which it is free to ignore. It's ideal for small bits of code.

If your function is inlined, it's basically inserted in the code where the function call is made to it, rather than actually calling a separate function. This can assist with speed as you don't have to do the actual call.

It also assists CPUs with pipelining as they don't have to reload the pipeline with new instructions caused by a call.

The only disadvantage is possible increased binary size but, as long as the functions are small, this won't matter too much.

I tend to leave these sorts of decisions to the compilers nowadays (well, the smart ones anyway). The people who wrote them tend to have far more detailed knowledge of the underlying architectures.