Moving inline methods from a header file to a .cpp

2019-01-28 07:17发布

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:

  1. Is my statement about the removal of the inline keyword correct? Should it be necessarily removed?
  2. How typically the removal of the inline keyword affect the performance (practically all my methods are inlined)?

Thank you very much in advance.

6条回答
男人必须洒脱
2楼-- · 2019-01-28 07:48

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.

查看更多
ら.Afraid
3楼-- · 2019-01-28 07:49

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 it inline to avoid linker errors.

查看更多
Emotional °昔
4楼-- · 2019-01-28 07:56

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 for unresolved 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...

查看更多
戒情不戒烟
5楼-- · 2019-01-28 08:02

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 as inline, 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.

查看更多
Bombasti
6楼-- · 2019-01-28 08:02

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 ignore inline 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:

int foo() { /* do something */ }
int foo() { /* do something else */ }

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 as inline, 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:

struct Foo {
    void bar() { /* do something */ }
};

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 inlineing them is redundant.

查看更多
Emotional °昔
7楼-- · 2019-01-28 08:07

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:

An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case (3.2). [ Note: A call to the inline function may be encountered before its definition appears in the translation unit. —end note ] If the definition of a function appears in a translation unit before its first declaration as inline, the program is ill-formed. If a function with external linkage is declared inline in one translation unit, it shall be declared inline in all translation units in which it appears; no diagnostic is required. ...

查看更多
登录 后发表回答