views:

220

answers:

11

Hi, I am making a Qt application and as I was coding, I took the habit of defining my slots in the header. I found it was easier for me to develop that way though I still define normal functions in the .cpp (unless the function is really small). But now there are some worries from my colleague that putting these in the header is bad practice because the fact of defining them in the header makes them inline so I am looking into the matter to understand everything that is going on. This is the reason I was given:

"Even in-lined functions (other than as required by classes) is a highly debatable practice. In theory, it creates faster, but larger code (avoids function calls and returns by duplicating code). However, several people have noticed that often using in-lining actually creates slower code. The reason why is because it can cause the code to get larger and exceed the size of what fits in one or more caches used at run-time. As a result it causes portions of the function to go in and out of cache every pass through some loop and the cache misses and subsequent reloads are far more costly than a function call to something already in another cache page. It’s an interesting situation and one that can’t be predicted, only observed by trial and error."

+1  A: 

Defining functions in the header gives the compiler the choice of making them inline. It will do so if it thinks the result will be more efficient, which might change based on whether you asked for the fastest or smallest code. The function might get defined in multiple object files, but the linker is supposed to detect that and eliminate the duplicates.

Mark Ransom
+1  A: 

Visual Studio supports

__declspec(noinline)

see http://msdn.microsoft.com/en-us/library/kxybs02x%28VS.80%29.aspx

Probably other compilers have similar constructs.

RED SOFT ADAIR
Unless you have a huge amount of evidense that the compiler is inlining when it should not be. Then avoid this like the plague. The compiler is much better at making these decisions than any human.
Martin York
+25  A: 

Your colleague needs to check up on the meaning of inlining in C++.

There are two meanings of the word, and it's important to keep them separated:

According to the C++ standard, a function is inline if it is marked with the inline keyword, or defined inside the class definition.

The only required effect of this, is to disable the One Definition Rule -- that is, to make it legal for the definition to be seen in multiple translation units without producing a linker error. Basically, it allows you to put the full definition in a header file

Then there is the "inline" optimization, which consists of taking the function body, and inserting it instead of a function call.

These meanings are almost entirely orthogonal. A function can be inlined by the compiler whether or not you, the programmer, marked it as inline. (Although it is harder and less common for a compiler to be able to inline if the function is called in a different translation unit than the one in which it was defined) A function marked inline in C++ may or may not be inlined by the compiler. The compiler tries to estimate the possible benefit of this, based on code size, how frequently the function is called, number of call sites and such heuristics. The result is that the compiler is pretty good at determining when the inlining optimization is worthwhile, and your best bet is usually to leave it to do its thing alone.

You should simply mark functions as inline when 1) it is convenient for you, and 2) you want to ensure that the compiler has the option of applying the inlining optimization.

But you're not forcing the compiler to inline anything. You're merely arranging the code so that it can, if it chooses to do so, inline the function call.

jalf
Just adding to this very well-written answer: Do not fall for the temptation to use pragmas or other means that might be available to force the compiler to inline or not, unless you really know what you are doing. Otherwise you are definitely doing premature optimization, and will likely worsen things.
Josef Grahn
By the way, a way to enable the compiler to make better guesses at what should be inlined is by profile-guided optimization. Most popular compilers support this these days. And it will likely yield far better results than manually trying to predict what should or shouldn't be inlined.
jalf
thanks for your great answer
yan bellavance
+1  A: 

for me, the main reason weather to have the implementation in the H or CPP file is depended with how public is the H file. If the H file is used to define a public interface with other modules (usually meaning, the corresponding CPP file is not compiled together with files that include the H file), I would like to include as little implementation as possible in the H, and implement everything in the CPP.

Yuval
+5  A: 

Since those methods are slots, they won't be inlined. Slots by definition are called by pointer to function. Even if they are explicitly declared inline, compiler will have to generate normal function code for them, so their pointer can be taken.

The only problem (if you see it as such) is longer compilation time caused by recompiling the same method in all compilation units that include your class definition and then removing duplicate versions while linking.


As others stated inline in C++ doesn't mean that compiler will inline function. And the other way around: lack of inline will not stop strongly optimizing compiler and linker from inlining some function when they think it'll speed-up the program.

Inline in C++ says only one thing to the compiler: This function is defined in header file and so it may be compiled independently in multiple compilation units. It is not an error so don't emit any error or warning message. Instead, during consolidation multiple versions of this function should be treated as one. Compiler isn't even obligated to check if those multiple versions are consistent.

Tomek Szpakowicz
+1  A: 

If the function is a class member, declare the function to be virtual.

KitsuneYMG
+1  A: 

As others have already pointed out, the compiler is free to do as it likes, and if the functions are big it will most likely not inline them.

However, there are other reasons why you might not want too much code in the header files. One is compile time; if the header is included in many different .cpp files you'll be giving the compiler a lot more to parse.

Another reason might be that you're exposing parts of the implementation, if you or your employer intend to distribute the code as a closed source library.

So you'll have to weight the pros and cons, but inlining is not one of the cons.

Josef Grahn
A: 

I suggest you create a pointer to the function or method. This is not a guarantee, but methods that are pointed to will have an address. Generally, inlined methods cannot have pointers referencing them. Although compiler implmentors are allowed to figure ways around this.

Thomas Matthews
and what'd be the point? Why would you use this kind of hackery to *prevent* the compiler from inlining?
jalf
A: 

The accepted answer is correct in what it says and yet totally irrelevant. Your concern is the actual inlining of code, and yes that will be affected by doing everything in the header unless you take specific measures to avoid this.

However, this is almost always what you want. The cases where it isn't will generally be too unwieldly for you to maintain anyway. That is, they will be too much text and you will no doubt wind up separating them out. Also, with templates it can be a problem since you need to remember it could be generating many actual methods that way and it's not smart to assume it knows what it can and can't throw out because normally it doesn't.

Charles Eli Cheese
A: 

A reason to not write inline code is for any class that is externally visible in dynamic libraries.

  • Inline code forces recompiling all library users if that code changes.
  • Linking C code to a C++ library with exported C functions and a minimal C header becomes impossible because the final result does not contain the inlined code.
  • There was also some mess with typeid information that I cannot remember all the details of.
Zan Lynx
A: 

Just responding to this:

Even in-lined functions (other than as required by classes) is a highly debatable practice. In theory, it creates faster, but larger code (avoids function calls and returns by duplicating code). However, several people have noticed that often using in-lining actually creates slower code. The reason why is because it can cause the code to get larger and exceed the size of what fits in one or more caches used at run-time. As a result it causes portions of the function to go in and out of cache every pass through some loop and the cache misses and subsequent reloads are far more costly than a function call to something already in another cache page. It’s an interesting situation and one that can’t be predicted, only observed by trial and error.

Your colleague seems to be willing to throw out a perfectly good technique altogether because in some cases it can mess with instruction cache efficiency. Most programs running on most systems don't require much micromanagement of the instruction cache.

In the common case, you're far more likely to get a performance gain out of inlining than you are out of this kind of micromanagement. Plus the compiler will inline for you anyway unless you specifically disable it.

There's a lesson here, and it's that you should pay very close attention to what your compiler does with performance-intensive code. But for the other 80% of your code, the compiler will normally do the right thing on its own.

(Also it's probably worth pointing out that inlined code will not always be larger than the original code. I've often observed this to be the case with heavy floating point or SIMD code.)

Dan Olson
If you inline "in the common case", you can wave your performance goodbye. It will certainly hurt the i-cache, no matter your CPU.
jalf
The common case is to let your compiler handle it, not to inline everything. Most people don't need to worry about icache performance. There will be other bounds to take care of long before that becomes an issue on most platforms.
Dan Olson