I have the following class defined in a foo.h
header file
class Foo {
public:
inline int Method();
};
inline int Foo::Method() { // Implementation }
I would like now to move the implementation to a foo.cpp
file. To this end, I have to remove the inline
keyword and move the implementation of the method to a foo.cpp
file like this
#include `foo.h`
inline int Foo::Method() { // Implementation }
I have two questions:
- Is my statement about the removal of the
inline
keyword correct? Should it be necessarily removed? - How typically the removal of the
inline
keyword affect the performance (practically all my methods are inlined)?
Thank you very much in advance.
2. How typically the removal of the inline keyword affect the performance (practically all my methods are inlined)?
The
inline
keyword tells the compiler to take the implementation code of that function and put it in place of the function call. This reduces the number of function calls on the stack and if used correctly, can improve the performance of your program.The
inline
keyword should only be used with small functions. Get and Set functions are good examples. They set the value of one variable or return the value of one variable.If you make a function with a lot of code
inline
, it can increase the size of your code by a lot (depending on the size of the function code and how many times that function is used) and actually DECREASE the performance of your program.It may be confusing, but you should not think of the purpose of
inline
to make the compiler inline a function. (Modern compilers are way smarter than you in regards to when a function should be inlined or not anyway).No, the real purpose of
inline
is to tell the linker to not worry about multiple definitions of the function. If you put the definition of a (non-member) function in a header, you should mark itinline
to avoid linker errors.If the function isn't TINY (or takes several arguments, but doesn't do much, such as a constructor or similar, that takes a bunch of things, and just copies it to somewhere inside the class), inlining it will have little impact on performance in the first place. Setters and getters are usually good candidates to inline, since they (typically) just copy data from one place to another, and can easily be done where the call takes place.
As others have said, it's a "please compiler, if I may ask you kindly, consider inlining this function" - it's not a "make this function inline". The compiler, on the other hand, will often inline functions REGARDLESS of whether there is an
inline
keyword. It looks at the size of the function, the number of calls and how much larger the code gets from inlining.If you move the function to "foo.cpp", it will ONLY get inline inside the "foo.cpp" compile unit (typically, compile unit = source file).
That is unless you have a compiler capable of "whole program optimization" or similar tricks, and enable that feature - this basically means that instead of producing a ready to link object file with machine code, the compiler produces a "parsed, but not completely translated to machine instructions" object file. Then, when it comes to finally putting the executable (or shared library) toegether, the compiler/linker will produce one large lump of machine code from the "halfway" code. Both MS and GCC do support this, but I don't know how well it works for large projects.
Edit:
As per Mooing Duck's comment: An
inline
function doesn't make a real function name in the object file, so the linker may also give errors forunresolved symbol int Foo::Method()
[or some wording to that extent].End edit.
If performance is critical, you should measure the current code's performance, then make your changes, and measure it again. If it's significantly different, you'll have your answer. If it's faster (because of less inlining leading to more cache-hit rate for other bits of code, for example), then that's good. If it's slower, you'll have to put back (some of) the functions into the header file. Or live with it being slower... Or find some other way of making it faster again... The choices are yours (and, if you work in a group, some other people may have a say in the final decision, of course). It's almost impossible for anyone to say for SURE which way it will go without at the very least understanding the whole programs architecture and what goes on in the class - which, given the name "foo.cpp" in the post is probably not the REAL code...
If you moved the function definition from a header to a cpp file, you MUST remove the
inline
keyword all all locations for that function. With older linkers it might make things slightly slower, but with modern linkers you should notice no real difference in performance.*There are certain cases where a public member function can be
inline
, but that's just a bad idea. Don't do it. Arguments can be made for marking certain private member functions asinline
, but in reality what you really want in those to be__attribute__((always_inline))
or__forceinline
*In extremely rare cases it will make a difference, but 99% of the time it won't, and 99.9% of what's left you don't care. If measurements show you hit that one-in-ten-thousand, you can use the aformentioned
__forceinline
.You, and the people here giving advice about small functions, are looking at
inline
the old-fashioned way.inline
used to mean "I want this code to run quickly, so whenever I call this function, I want you to expand it in-place to avoid the overhead of a function call."That's a really good optimization. It's so good, in fact, that the compiler will eagerly do it even if you don't specify
inline
.The compiler is also free to not expand your
inline
functions. So you really don't have to worry about how it will affect performance, because the compiler can and will ignoreinline
if you use it in a stupid way.In fact, compilers today almost always ignore your use of
inline
, and just do whatever they think is best.So, knowing that, why do people still use
inline
?There's only one reason to use
inline
nowadays, and that's to work around the One Definition Rule (ODR).In C/C++, you're only allowed to define a function once. If you do this:
the compiler will complain that you've defined the same function twice.
That looks like a silly example, but it's particularly easy to do something like that when you're using
#include
- if you defined your function in a header, and you#include
the same header twice, this is exactly what you're doing.Thankfully,
inline
has another use which is still valid today: if you mark a function asinline
, it forces the compiler to silence ODR issues, making it possible to define your function in a header.In other words,
inline
now means "I want to define this function in a header."When you look at it that way, it should be clear that you should remove the
inline
when moving the function into a cpp file.For interest sake, there's a couple places where functions are implicitly made inline. One of them is in class member functions:
I've seen people mark functions like this
inline
, but that's completely redundant. The compiler does it anyway; there's no need to worry about ODR, and there's no performance to be gained.The other place is in templates. Since templates have to be defined in headers, they're exempt from the ODR, and
inline
ing them is redundant.Keyword
inline
is redundant in the class. It is implied if you have a function body.In the implementation file it is also fairly redundant.
The only use of it is if you define a free function in a header (or a member function outside the class, but in the header) to avoid multiple bodies.
Optimization-wise on mist modern compilers it's even more redundant, they inline anything in sight without question anyway, or ignore your keyword at will.
The inline usage must be consistent! From 7.1.2p4: