Inlining Functions in C++
27 October 2006, lunch time
The inline
keyword is used in C++ as a hint to the compiler that a function you are writing should not be treated as a normal function, but should instead be treated as a macro. When the compiler encounters a call to such a function in the source code it is processing, it will replace that function call with the function’s source code, its body. This should make your program faster. (A function call is a slightly involved process.) You inline a function by prefixing its definition with the keyword inline
.
You need to use the keyword when you declare the function, and when you define it. The same is true for methods (functions within classes). However, any method whose declaration is also its definition — methods which you define inside the class declaration itself — are inlined by default. So, the following functions in this simple class are marked as being inline automatically, whether you want them to be or not:
class MyClass {
void MyFunction() {
return;
}
void MyOtherFunction() {
return;
}
};
- Download this code: /static/code/11.txt
The key thing to remember is that the inline
keyword is just a hint. The compiler can choose to ignore your hint, and do as it pleases. Until compilers and linkers are particularly clever, your best bet to ensure that your functions are inlined is to make sure the definition and declaration of your function are both visible to the compiler during compilation. This usually means that the header file that contains the definition of your function will also contain the declaration, the function body.
When writing classes, best practice, in my opinion, would be to include the methods you want to inline at the end of the class’ header file, via the #include
macro, and use the inline
keyword inside the class definition. This is really just a matter of taste, but I think it keeps your header files neat and tidy:
class MyClass {
inline void MyFunction();
inline void MyOtherFunction();
};
#include "myclass.inl"
- Download this code: /static/code/12.txt
It is best not to go overboard inlining functions and methods. Really simple functions and methods are best inlined, and anything mildly complex should be left alone. Your compiler itself will probably refuse to inline anything with loops and complex control-flow. You should almost always use inlined functions over C-style macros: You get all the benefits of macros, and your compiler will make sure you aren’t mucking stuff up.
And now you know a little bit about the inline
keyword.
You can get aroung this in GNU C by using -fno-default-inline.
If you’re going to be putting inline functions in your header file, it’s probably adviseable to use the __ inline __ (ignore the spaces before and after ‘inline’) alternative keyword that’s ignored by -ansi and -traditional. But then you’d have to declare a macro that replaces inline with ‘inline’ for compilers that don’t have it defined.
(ignore the spaces around the underscores again)
And then you have to much about your makefile to make sure the dependencies get transfered properly (especially the inlined changes).
Lucky you inserted that ‘almost’ haha. I was going to bring up a hypothetical situation involving the insertion of a subsection of code that, by itself, isn’t a compileable unit of code, in multiple places and at the same time have the code act on the current scope it’s inserted into. You can’t have break statements break out of inline functions ;;
Then I think you’d have to use a macro. That, and inlining a commonly used function might blow up your code by a huge amount (causing thrashing and then you lose performance you thought you were gaining from inlining the function in the first place).
Also, when the inline function is not declared as ‘static’, the compiler has to assume that there may be calls from other source files and the function is compiled on its own as per the usual case anyway.
You’d probably want to declare your inline functions as ‘extern’ to get macro-like behavior, since then the definition will only be used for inlining, and the function won’t be compiled on its own, even if you reference its address explicitly (since then the address would just be an external reference).
Also, GNU C++ (and I’m pretty sure most compilers) won’t inline functions unless you have some sort of optimization level turned on. Macro’s will always be replaced though.
Type safety is only an issue if you want to be safe from types!
I think it’s just safe to say that if you don’t know what you’re doing, you’re doing it wrong haha.
by Iluvitar on October 27 2006, 4:29 pm #
Lots of good points. Scott Meyers has a great essay in one of his books on using inlining rarely, for many of the reasons you point out. Some of the esoteric errors you can come across would be a bitch to track down I think.
(I wrote this post some time last year. I don’t know why I did, or why I didn’t post it then.)
by ramanan on October 27 2006, 4:32 pm #