Join the Stack Overflow Community
Stack Overflow is a community of 6.5 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

In this link, what is an inline function and what is the inline keyword is explained. I'm reading through it because I realized I've never understood the meaning of these two concepts and how they should be used in practice. I'm quoting and commenting from the link I provided

An inline function or inline variable (since C++17) is a function or variable (since C++17) with the following properties:

1) There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is include'd in multiple source files.

Here I already have understanding problems, declaration is the specification of new identifiers like

void func(void);

while a definition is the actual implementation, including the body

void func(void) {
  //some code...
}

The point 1) means that I can give different implementation as long as they're in different translation units (i.e. one implementation per header e per source files), but I'm puzzled in the case I have a source file source.cc with a declaration for func and an header file with another declaration of func the translation unit is the pair source.cc+header.h and in such a case having declared two times func doesn't make any sense, is that right?

2) The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access).

This is the usual case where I separate definition from declaration, the first in an header file, the second one is in the source file, if I need to use the function I have to include only the header right? The access point would be provided by the source during the linking phase, correct?

3) An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties: 1) It must be declared inline in every translation unit. 2) It has the same address in every translation unit.

Could you provide a simple example of what this means? I can't picture a practical case of such a case. The case 3) states that the keyword inline is mandatory unless the function to be declared is static.

Is everything I said so far correct?

In practice a function should be inline when such a function is very small, but not always the compiler would inline the function declared as inline, for example if it has loops inside or recursion (Effective C++ states so). In general then it's compiler dependent, I the wonder now...

Say I have two functions the first one is self-contained (it doesn't internally call any-other function), the second one call's the first one (you can assume they're both 10 lines for sake of argument). Should both of them declared inline? should they be declared in an header file? or should I separate definition in an header file and the implementation in an source file? What would be better?

share|improve this question
1  
Imagine you say #include "source.cc" in multiple translation units. – Kerrek SB 11 hours ago
    
You can have multiple implementations of an inline function in C++, but they cannot be different from each other. C++ explicitly requires all the definitions of an inline function to be identical. C differs in that regard, however. – John Bollinger 7 hours ago

Maybe a few examples would help.

1. Traditional compiled library

foo.h:

extern int x;
int * f();

foo.cpp:

#include "foo.h"

int x = 25;

int * f() { return &x; }

Users include foo.h and need to link in the translation unit containing foo.cpp in order to call f. Every such call returns the same address.

2. Separate, TU-local variables

foo.h:

static int x = 35;
static int * f() { return &x; }

Every TU that includes foo.h gets a separate and distinct function f, calling which results in a unique value per TU.

3. Baby's first ODR violation

foo.h:

static int x = 45;
inline int * f() { return &x; }

This appears to be a header-only library, but if foo.h is included in more than one TU, this constitutes an ODR violation, since f would be defined more than once but not all of its definitions would be identical.

This is a common mistake. Workarounds include things like making x a template or replacing x with a function like int & x() { static int impl = 45; return impl; }. Note that if you omit the static, you would most likely get a linker error because of multiple definitions of x; static seemingly "makes the code compile".

4. C++17 to the rescue: Proper header-only libraries

foo.h:

inline int x = 55;
inline int * f() { return &x; }

This version is functionally equivalent to (1), but does not require a dedicated translation unit to contain the definitions of x and f.

share|improve this answer
    
@Barry: Thanks :-S Bad habits... – Kerrek SB 7 hours ago
    
NP! it's a great answer. Just fixing the typo. – Barry 6 hours ago

Let's put the issue of whether inline is forced or not, aside for now (there are lot's of discussions on the topic).

Inlining a function is equivalent of pasting the contents of the function at the location of the function call (invocation).

So given the following:

void Hello()
{
  std::cout << "Hello\n";
}

int main()
{
  Hello();
  return 0;
}

When the Hello function is inlined, you will get the equivalent of:

int main()
{
  // Hello();
  std::cout << "Hello\n"; // This is the content of function Hello().
  return 0;
}

The compiler is allowed to inline functions that are not marked as being inlined. This feature is often triggered by an optimization setting.

Edit 1: Common reason for inlining
A common reason for inlining a function is when the content is smaller or equal than the overhead to call the function.

There is a protocol associated with call a function, such as moving parameters to the stack or registers. The protocol exists regardless of the size of the function. So, inlining will remove the calling protocol (thus reducing program code size and increasing performance).

Another reason to inline is to reduce the quantity of function calls. In some processors, a branch instruction (function call), causes the instruction cache (or pipeline) to be reloaded. This takes time. Inlining reduces the function calls and improves execution time.

Edit 2: Code Bloat
One reason to create functions is to reduce code size. Inlining of large functions may result in code bloat or the increasing of the program's size.

Code bloat and function inlining are under the Time versus Space trade off. Inlining of large functions may speed up execution, but you are trading space for it. Place common code into functions may decrease the size of your program, but take more time to execute.

share|improve this answer
    
It's like a macro, except that is the compiler figures out when doing the expansion or not, this is all I know. However I would like to have a more deep insight about it (a technical insight). – user8469759 10 hours ago
    
Please clarify "a deep insight". Do you need information about compiler theory? Do you want to know the criteria a compiler uses for when to inline? Do you want information about processor instruction caches, pipelines or parallel execution? – Thomas Matthews 10 hours ago
    
In the C language, a common idiom is to create a macro for a function in order to get the inlining. – Thomas Matthews 10 hours ago
    
Grammar glitch in "Edit 1: Common reason for inlining" paragraph 1: "smaller or equal than" – user4581301 10 hours ago
2  
The keyword inline has two radically different meanings. The "human" meaning: it's a function whose code is pasted at the site of each call. The C++ meaning: it's a function that has special handling with regard to ODR (see other answers for details). There is little overlap between these meanings. I think OP asks about the C++ meaning, and this answer doesn't mention it at all, which can lead to confusion. – anatolyg 8 hours ago

The point 1) means that I can give different implementation as long as they're in different translation units

No, it says you can have more than one implementation. It does not say they can be different. The implementations must all be identical.

I'm puzzled in the case I have a source file source.cc with a declaration for func and an header file with another declaration of func the translation unit is the pair source.cc+header.h and in such a case having declared two times func doesn't make any sense, is that right?

You can declare a function as many times as you like, in as many translation units as you like, regardless of whether or not it is inline. Inline is not a factor here.

2) The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed.

This is the usual case where I separate definition from declaration, the first in an header file, the second one is in the source file, if I need to use the function I have to include only the header right? The access point would be provided by the source during the linking phase, correct?

No, the definition of an inline function must be present in every TU that uses it, before the linking phase. It is the purpose of inline functions to allow definitions in multiple TUs; you use inline when you want to put the definition of a function in a header.

The case 3) states that the keyword inline is mandatory unless the function to be declared is static.

No, it doesn't say that at all, I don't know how you could have interpreted it that way. It just says that an inline static function has internal linkage, and an inline non-static function has external linkage, and subpoints 3.1 and 3.2 apply to inline functions with external linkage.

In practice a function should be inline when such a function is very small, but not always the compiler would inline the function declared as inline, for example if it has loops inside or recursion (Effective C++ states so). In general then it's compiler dependent, I the wonder now...

Say I have two functions the first one is self-contained (it doesn't internally call any-other function), the second one call's the first one (you can assume they're both 10 lines for sake of argument). Should both of them declared inline? should they be declared in an header file? or should I separate definition in an header file and the implementation in an source file? What would be better?

Whether or not the optimizer will perform inline substitution of a function body is not strongly correlated with whether it is an inline function. The optimizer will figure out for itself whether to perform inline substitution of a function, regardless of whether or not it is an inline function. You declare functions inline if you want to put their definition in a header.

share|improve this answer
    
This is far and away the clearest answer that actually addresses the question, IMO. Well done. – Lightness Races in Orbit 6 hours ago
    
It's funny how I misunderstood all the three points xD. – user8469759 6 hours ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.