C++: proper inlining syntax
Is it preferred to define inline methods like:
// math.h
class Math
{
public:
inl开发者_StackOverflow社区ine static int sum(int a, int b)
{
return a + b;
}
};
or
// math.h
class Math
{
public:
static int sum(int a, int b);
};
// math.cpp
inline int Math::sum(int a, int b);
{
return a + b;
}
and why? Is there any difference? Should you leave inlining entirely up to the compiler? (I know this is pretty subjective but I'd like to hear some opinions and reasons)
Also, I believe it is true that most compilers will inline or not inline of their own accord regardless of the presence or absence of the inline keyword?
No matter what, you are leaving inlining entirely up to the compiler. Those are just hints that you believe the code should be inlined (or not). All methods defined in the class definition are by default inline (with the actual meaning of inline
that is not must inline this method).
class Math {
public:
static int sum( int a, int b ) // inlined even without 'inline'
{ return a+b; }
};
Whether you use the in-class or out of class inline versions (both in the header) is up to you, and I would base that on readability. For small one-liners and accessors I tend to write them in-class as that is the most powerful documentation of the method and the code still lets you see the class interface easily.
Inlining is entirely up to the compiler. The inline
keyword, like the old C register
keyword is a suggestion to the compiler to do some optimisation.
However, compiler writers know so much more than we lesser beings about their target architectures that this is really unnecessary.
Because of that, I don't ever use inline
so the question is moot (for me) but I would prefer to keep all code out of headers since that always led to double-defined symbols in C compilers.
Putting code in header files also leaks information unnecessarily. People using your headers should not be able to see the implementation details.
The trouble if you use your second method, is that when compiling other source files that include math.h
, they won't know the definition of your Math::sum
function. Therefore, they will not be able to inline it.
That's why you should put the definition of the function in the header file. But note that you can write it after the definition of the class. It is not mandatory to write it within.
What we use in my company is a common trick to help better trade-offs in both debug and release versions. You don't really care for inlining in debug versions, but you would prefer decoupling the inlined code to avoid long recompiling times when you touch the inlined code. So we do this:
// math.h
class Math
{
public:
static int sum(int a, int b);
};
// At the very end of math.h
#ifndef _DEBUG
#include "math.inline.h"
#endif
// math.inline.h
#ifdef _DEBUG
#define INLINE
#else
#define INLINE inline
#endif
INLINE int Math::sum(int a, int b);
{
return a + b;
}
// math.cpp
#include "math.h"
#ifdef _DEBUG
#include "math.inline.h"
#endif
This way, the full contents of math.inline.h go to exactly the same place in both versions (right at the end of math.h), but they are only included with the header in the release version. The debug version includes them along with the implementation file and never tries to inline the functions.
Your second way will make that no translation unit other than math.cpp
is allowed to call Math::sum
, because the Standard says that inline functions shall be defined in every translation unit in which they are used. Entirely possible this gets you a link-time error (i've run into this problem before).
Always define inline functions in the header to avoid this problem.
It doesn't make much difference from compiler's point to use any of these two methods
But generally, its preferred for header files to contain only declarations , Just specification of class interface so that anyone can look in header file and need not go into how functionality is implemented. So, its better to have interface specification in header file and implementation in .cpp file
Compilers can generally move code across translation units so the two should have no difference. Personally I prefer this (all in the header):
// math.h
class Math
{
public:
static int sum(int a, int b);
};
inline int Math::sum(int a, int b)
{
return a + b;
}
The reason I prefer this is that there are times when even the best optimizing compilers cannot inline code if you put it in the cpp file, like if the math class was being exported (no inlining across DLL boundaries, e.g.). I don't like to make exceptions to my coding style, so just putting it in the header is guaranteed to allow the compiler to inline it (if it so chooses).
The second reason I prefer this explicit style over inlining directly in the class definition is because I work with a lot of lazy coders who often inline things just because it saves time to write instead of actually inlining after a profiling session (which is generally the only time you should consider inlining unless you are a superb compiler/assembly genius).
As an important side note, it is quite common to find that inlining makes no noticeable improvement in performance, and there are many cases where not inlining code is better than inlining it. I've found this to even be true of simple one line accessor functions: just because the code, when inlined, requires fewer instructions than it does to call the function doesn't always mean the compiler will do a better job with it. Over-inlining can actually confuse compilers (ex: not using registers very effectively because of too much inlined, exceptional-case code accessing memory). Inlining really should be done with care and the aid of a profiler.
Sometimes the first version can act as a form of documentation when the method is a one-liner.
精彩评论