Inline Functions

Started by
9 comments, last by JasonBlochowiak 17 years, 8 months ago
Hello, This is kind of a question just so I make sure Im getting this correctly. Inline source:

#include <iostream>
using namespace std;

int radiation(int health);

int main()
{
    int health = 80;
    cout << "Your health is: " << health << "\n\n";
    
    health = radiation(health);
    cout << "Your health after radiation: " << health << "\n\n";
    
    health = radiation(health);
    cout << "Your health after radition: " << health << "\n\n";
    
    health = radiation(health);
    cout << "Your health after radiation: " << health << "\n\n";
    
    return 0;
}

inline int radiation(int health)
{
    return (health/2);
}

Now, this basically works like this, right? It copies the function and it puts it into the calling function, so it doesnt jump all over the place.

#include <iostream>
using namespace std;

int main()
{
    int health = 80;
    cout << "Your health is: " << health << "\n\n";
    
    health = health/2;
    cout << "Your health after radiation: " << health << "\n\n";
    
    health = health/2;
    cout << "Your health after radition: " << health << "\n\n";
    
    health = health/2;
    cout << "Your health after radiation: " << health << "\n\n";
    
    return 0;
}

Advertisement
Yeah, but Inlining is up to the compiler. If the compiler doesn't think it will make a difference it doesn't inline. Inlining isn't usually needed at all. But if you use that function 100,000 times, Inlining may improve your program speed quite a bit ;)
___________________________________________________Optimists see the glass as Half FullPessimists See the glass as Half EmptyEngineers See the glass as Twice as big as it needs to be
Basically, yes, that is correct. However, you should note that just because you declair a function as inline does not necessarily mean it will be inlined, and if a function is not declaired inline, it may still be inlined. It all comes down to how your compiler optimizes your code. Declairing a function inline is basically a suggestion to the compiler that you think this function should be inlined. The compiler is free to disregard your suggestion if it thinks your code would be more efficient without inlining the function.

(more info here)

Edit: Slow!
Put the inline function before the functions that use it. C++ typically compiles from top to bottom, and when it compiles main() it won't yet know that you wanted radiation() to be inline, so main() will treat it as a normal function, which means that it'll generate a normal function body for radiation() anyway.

Some compilers might be intelligent enough to get around this, but I wouldn't put money on it.
Hi,

Quote:Original post by Kylotan
C++ typically compiles from top to bottom, and when it compiles main() it won't yet know that you wanted radiation() to be inline


I do not agree with this statement. Modern compilers make several passes of the source, or rather from the text source file will generate various intermediate representations (typically Abstract Syntax Trees, Code Intermediate representation trees, call graphs etc.) that give it the neccessary information at various stage of compilation. For this reason I do not believe that modern compilers would not know that the radiation() function was requested to be inlined.

[EDIT: irrespective of where it is declared in the file]

Basically as everyone else said its a compiler hint. Some compilers (particularly compilers for embedded systems) contain a force inline directive that can be used to force the compiler to inline function but this is rarely needed as compilers tend to be better at deciding this kind of thing :)

What I would recommend doing is getting your compiler to output the assembler output to a file and then you should be able to read that to determine whether the method is being inlined or not.

Cheers,
dhm
What you assume it is ok. Even though the compiler will replace the function, you should have in mind that the code of the first example will be a little bit slower than the second one since the function uses a copy parameter. Moreover, using variables by reference in the functions of the first code won’t make the code as fast as the second one because the access of a dereferenced variable, which is inside a function, has an associated cost, so unless you don’t use any parameter in an inline function the speed will always be faster in the second example.
Quote:Original post by dhm
Hi,

Quote:Original post by Kylotan
C++ typically compiles from top to bottom, and when it compiles main() it won't yet know that you wanted radiation() to be inline


I do not agree with this statement. Modern compilers make several passes of the source, or rather from the text source file will generate various intermediate representations (typically Abstract Syntax Trees, Code Intermediate representation trees, call graphs etc.) that give it the neccessary information at various stage of compilation. For this reason I do not believe that modern compilers would not know that the radiation() function was requested to be inlined.


What I said may have been misleading. In general C++ compilers are not required to make multiple passes over the source; after all, if they did, many things that the language requires would not be necessary. But of course they may do so, in order to improve your code, but all your declarations have to make sense as if they are being compiled in one pass. At some point, it does have to start generating code, and it's not always practical or even possible to determine a perfect order to do this that won't miss any chances at optimisation. (Though this is not such an example.) So ideally you want the compiler to know that the function is inline before it ever attempts to use it. Compilers do a lot of great stuff but occasionally they miss a simple trick.
Quote:Original post by martins77
What you assume it is ok. Even though the compiler will replace the function, you should have in mind that the code of the first example will be a little bit slower than the second one since the function uses a copy parameter.


Actually, the code of the above examples compiles to this, on gcc and Visual C++ 2005:

cout << "Your health is: " << 80 << "\n\n";cout << "Your health after radiation: " << 40 << "\n\n";cout << "Your health after radiation: " << 20 << "\n\n";cout << "Your health after radiation: " << 10 << "\n\n";return 0;

It removes the divisions or function calls entirely since it has all the information it needs in this case to do so. But your point may be valid under some other circumstances. (Though not all; some C++ optimisations seem to require a return by value rather than a return by reference.)
Quote:Original post by Kylotan
What I said may have been misleading. In general C++ compilers are not required to make multiple passes over the source; after all, if they did, many things that the language requires would not be necessary. But of course they may do so, in order to improve your code, but all your declarations have to make sense as if they are being compiled in one pass. At some point, it does have to start generating code, and it's not always practical or even possible to determine a perfect order to do this that won't miss any chances at optimisation. (Though this is not such an example.) So ideally you want the compiler to know that the function is inline before it ever attempts to use it. Compilers do a lot of great stuff but occasionally they miss a simple trick.


What? A compiler will have a perfect view of the call graph, or else it wouldn't be able to compile much of anything. Therefore, it will have a complete view of what functions have been hinted at inline and which haven't.

As others have pointed out, the compiler is free to ignore the keyword (just like the "register" keyword), but that's not a result of the compiler having an incomplete view of that aspect of the source.

On a somewhat related note, "Link Time Code Generation" lets the compiler do optimizations across modules, by doing compilation on a merged code tree.

And, while on the subject, people should not assume that inlining code will always make things faster. Inlining increases the likelyhood of blowing the instruction cache, sometimes with very negative results (there's a longer, rantier real-world example I gave about code size here).
Quote:Original post by JasonBlochowiak
What? A compiler will have a perfect view of the call graph, or else it wouldn't be able to compile much of anything. Therefore, it will have a complete view of what functions have been hinted at inline and which haven't.

C++ is single-pass compileable, so the compiler doesn't neccessarily have the complete graph.

No modern compiler is a single-pass compiler, but still it might use only the information given at the first declaration.

This topic is closed to new replies.

Advertisement