The use of functions provides many benefits, including:
- The code inside the function can be reused.
- It is much easier to change or update the code in a function (which needs to be done once) than for every in-place instance. Duplicate code is a recipe for disaster.
- It makes your code easier to read and understand, as you do not have to know how a function is implemented to understand what it does.
- The function provides type checking.
However, one major downside of functions is that every time a function is called, there is a certain amount of performance overhead that occurs. This is because the CPU must store the address of the current instruction it is executing (so it knows where to return to later) along with other registers, all the function parameters must be created and assigned values, and the program has to branch to a new location. Code written in-place is significantly faster.
For functions that are large and/or perform complex tasks, the overhead of the function call is usually insignificant compared to the amount of time the function takes to run. However, for small, commonly-used functions, the time needed to make the function call is often a lot more than the time needed to actually execute the function’s code. This can result in a substantial performance penalty.
C++ offers a way to combine the advantages of functions with the speed of code written in-place: inline functions. The inline keyword is used to request that the compiler treat your function as an inline function. When the compiler compiles your code, all inline functions are expanded in-place — that is, the function call is replaced with a copy of the contents of the function itself, which removes the function call overhead! The downside is that because the inline function is expanded in-place for every function call, this can make your compiled code quite a bit larger, especially if the inline function is long and/or there are many calls to the inline function.
Consider the following snippet:
int min(int nX, int nY)
{
return nX > nY ? nY : nX;
}
int main()
{
using namespace std;
cout << min(5, 6) << endl;
cout << min(3, 2) << endl;
return 0;
}
This program calls function min() twice, incurring the function call overhead penalty twice. Because min() is such a short function, it is the perfect candidate for inlining:
inline int min(int nX, int nY)
{
return nX > nY ? nY : nX;
}
Now when the program compiles main(), it will create machine code as if main() had been written like this:
int main()
{
using namespace std;
cout << (5 > 6 ? 6 : 5) << endl;
cout << (3 > 2 ? 2 : 3) << endl;
return 0;
}
This will execute quite a bit faster, at the cost of the compiled code being slightly larger.
Because of the potential for code bloat, inlining a function is best suited to short functions (eg. no more than a few lines) that are typically called inside loops and do not branch. Also note that the inline key word is only a recommendation — the compiler is free to ignore your request to inline a function. This is likely to be the result if you try to inline a lengthy function!
7.6 — Function overloading
|
Index
|
7.4a — Returning values by value, reference, and address
|
7.6 — Function overloading
Index
7.4a — Returning values by value, reference, and address
Ok
What happens when the compiled code becomes large by using the inline keyword? Why is it disadvantageous to have a large compile code?
Well, it takes up more space on disk, for one. It can also have a negative impact on how quickly your program executes due to the way the operating system pages stuff in and out of memory. Bloated code means more page loads, which adds overhead.
I don’t know what a page load means. Is this a different type of overhead because normally inline functions are meant to reduce overhead as explained in the text.
Page loading is actually an operating system concept and has nothing to do with C++ itself. It’s overhead that comes from the operating system itself due to the way memory is set up.
Your computer has a certain amount of physical memory on it. This memory needs to hold all the programs that are running. However, it’s sometimes the case that our programs want to use more memory than we have physical memory on the machine! In the old days, you’d probably get a memory error and your program wouldn’t run until you freed some stuff up. However, most modern operating systems use a system called virtual memory. Virtual memory is basically a technique that lets the operating system assign more memory to programs than it actually physically has!
The way this works is all of the physical memory in the machine is divided into chunks called pages. When a program is loaded, the operating system load it into how ever many pages it needs. However, if we run out of free pages, the operating system will make room by temporarily writing out some older pages to disk. This is what a swap drive is for. Then, when those old pages become needed again, it reads them back into memory from disk (and possibly writes out something else)
If you’ve ever run Windows XP (or Vista) on 512 megs of ram (or less), you know how slow it can be. Why? Because the operating system is writing pieces of itself out to disk and reading them back in all the time.
Bloated programs tend to cause the operating system to have to read in and write out more pages (for a variety of reasons). Since writing pages to disk is extremely slow, this is something you want to avoid as much as possible.
Ok then can we say that the inline keyword speeds up the execution only when the function is not too large otherwise it can cause the program to be even slower?
Abusing the inline keyword could, in theory, cause the program to be even slower than usual. However, there is no guarantee that this is strictly true, as there are other factors that come into play. For example: how many times the inlined function is used, spatial access issues (the pattern in which the code is accessed), as well as whether the compiler even pays attention to the inline request (which it is free to ignore).
As noted in the lesson text, inline is best used for functions that are no more than a couple of lines.
thanks for your clearification i agreee with your concept and could you please provide me information regarding tows
regarding os i’will thankfull to u….iam a student of bca 2nd sem
[...] 7.5 — Inline functions [...]
Wow! These tutorials are growing almost as fast as I can read them :)
Could you please explain the major differences between using an inline function and a #define macro?
Let me direct you to this article, which does a good job laying out the differences.
Personally, I never use #defines any more except for using in conjunction with #ifdef.
thanks, that explained a lot.
[...] 2007 Prev/Next Posts « 7.5 — Inline functions | Home | 7.7 — Default parameters » Friday, August 3rd, 2007 at 8:25 [...]
Thanks,that easy to understand ..:)
Is it advisable to make this function as inline? (It has loop which iterates for large number of times)
void fun1() { for(int i<0;i<10000;i++) { cout<<endl<<i; } }I wouldn’t — I only use inlines for functions that are absolutely trivial. Anything with a loop doesn’t qualify. I’m pretty sure if you put a loop in an inline function the compiler will just treat it as a normal function.
how would i know whether for above (for loop ) function, the compiler had accepted/rejected our request
of making the function inline..
the tutorials are very good..
Wow c++ is a lot more interesting and a lot harder than python I have to say!
:P
Hi Alex,
One quick question. When a compiler is smart enough to decide whether “inline” is applicable or not (based on some hidden criteria by compiler as you explained above), as a common practice why can’t we define each and every function as an inline function and leave it up to the compiler to decide whether to treat it as an inline or not. what could be the ups and downs by following such a style of coding?
i have the same question.
Well, I was thinking if the compiler is smart enough, why can’t it do this work implicitly… But, I too would like to know the answer to Jay’s question…
I don’t think compilers are smart enough to know whats best. It only knows very specific situations, where its definitely not efficient and will ignore inline under those conditions. but it certainly isn’t smart enough to make every decision for you.
[...] 7.5 Inline functions [...]
Alex, if an inline function puts the function code inside where the function was called, is it necessary to pass all parameters? Because I have a function that gets a lot of parameters and keep the same name and by reference, t would be much better if I don’t send all those parameters…
pls help solve this ,use for..loop structure to generate the following output
4 8 12 16
3 6 9
2 4
1
I have completed your homework for you, nas.
#include
using namespace std;
int main()
{
for (int iii = 4; iii > 0; iii–)
{
for (int jjj = 1; jjj <= iii; jjj++)
cout << jjj * iii << " ";
cout <> end;
return 0;
}
#include
using namespace std;
int main()
{
for (int iii = 4; iii > 0; iii–)
{
for (int jjj = 1; jjj <= iii; jjj++)
cout << jjj * iii << " ";
cout <> end;
return 0;
}
damn, won’t paste correctly, but hopefully you get the idea.
[...] template functions should be applied instead of function-like macros. (I think you know the famous min function, which can be implemented either via macros or via inline template function, the two different code [...]