When to use "inline"?

7

Everyone says that you do not have to use inline in the functions since the compiler knows what to do better than the programmer. But if it has in the language it should serve something.

Is it useful in any case? When to use it then?

    
asked by anonymous 14.02.2017 / 13:47

2 answers

6

inline exists to give a hint to the compiler what to do. It is in the specification of C and C ++ that is so.

The compiler does not need to follow this tip. It can linearize the function (put the content of the function where it should be called) without any hint, and can keep the call even with the hint.

Each compiler has its own rule on each platform and configuration. It is possible to ignore it completely without any rules.

The tip can be useful in cases where it is not so obvious what to do.

  • Do not waste time on large function (few lines are already large).
  • Functions with loops, even if it's a line, will not be linearized either (unless the loop is replaced by simple code, this if it can be guaranteed that it will only loop very often, maybe 4).
  • Functions that make I / O access never make up.
  • A function that is little used, which is not called in large loops, will give a minimum gain and may affect occupying the cache that would be useful for another better optimization.
  • Functions that can be used by third parties in external modules (DLLs) and that there may be some update. If it is linearized, the update will not be used until a new build.
  • Empty functions will almost always be linearized. If you do not want this to happen for the previous reason, use a noinline .
  • In C ++ builders and destructors will always have a code even if it is empty.

The noinline attribute is often used to "prevent" the compiler from linearizing the function. Each compiler has its way of using this non-default attribute. Obviously, each compiler can use whatever rule it chooses to choose to do or not.

There is a way to ensure that the function will not be linearized, but this creates an additional cost in its use by causing indirection extra:

void (*pFunc)() = func; //func é uma função definida em algum lugar
//a chamada
pFunc();

In recursive functions the attribute can even make the optimization transform a function into a constant value.

To help understand how the compiler works, check what it did in each case that uses the inline attribute.

Interesting article on the subject .

    
14.02.2017 / 13:47
2

Maniero's answer is, as always, excellent, but there is another semantic aspect of using inline which is less known.

The inline attribute causes a relaxation of the constraints imposed by the "One Definiton Rule". By default:

  

6 Basics

     

6.2 One-definition rule

     

10 Every program should contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of discarded statement >; 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 [class.ctor] , [class.dtor] and [class.copy] .    An inline function or variable shall be defined in every translation unit in which it is odr-used outside of a discarded statement.

(Emphasis mine)

This means that, instead of requiring that the function be defined in only one translation unit , the compiler will define the function with inline on each translation unit with the same definition .

As an example, assume that we have three files:

nop.h

void nop(){}

a.cpp

#include "nop.h"
int main(){}

b.cpp

#include "nop.h"

Compiling using the command g++ a.cpp b.cpp generates the following error:

(...): In function 'nop()':
b.cpp:(...): multiple definition of 'nop()'
(...):a.cpp:(...): first defined here
collect2: error: ld returned 1 exit status

Normally, the fix would be to create a fourth nop.cpp file, and adjust the nop.h file to contain only one declaration:

nop.h

void nop(); // Apenas uma declaração

nop.cpp

#include "nop.h"
void nop(){} // Definição

The other way, of course, is to simply transform the nop function into a inline function:

nop.h

inline void nop(){}
    
28.05.2018 / 20:03