Why are class member functions inlined?

vidit picture vidit · Mar 16, 2012 · Viewed 11.6k times · Source

I think my question has been asked here before, I did read them but still little confused and therefore asking to make it clear.

The C++ standard says all member functions defined inside class definition are inline

I have also heard that compiler can ignore inlining of a function. Will that be true in the above case or it will be always inlined if defined inside class definition?

Also, what was the reason behind this design, making all functions defined inside class definition inline? And what inlining has to do with source and header files?

Update: So one should always define their functions outside class if not to be inlined, right?

Update 2 by JohnB: Two functions declared inside class definition could never call each other as they would have to each contain the whole body of the other function. What will happen in this case? (Already answered by Emilio Garavaglia)

Answer

Emilio Garavaglia picture Emilio Garavaglia · Mar 16, 2012

Confusion arises because inline has two effects:

  1. It tells the compiler that the function code can be expanded where the function is called, instead of effectively being called.
  2. It tells the compiler that the function definition can be repeated.

Point 1. is "archaic" in the sense that the compiler can in fact do what it likes in order to optimize code. It will always "inline" machine code if it can and find convenient to do and it will never do that if it cannot.

Point 2. is the actual meaning of the term: if you define (specify the body) a function in the header, since a header can be included in more sources, you must tell the compiler to inform the linker about the definition duplicates, so that they can be merged.

Now, by the language specification, free functions (not defined in class bodies) are by default not defined as inline, so defining in a header a thing like

void myfunc()
{}

if the header is included in more sources, then linked in a same output, the linker will report a multiple definition error, hence the need to define it as

inline void fn()
{}

For class members, the default is the opposite: if you just declare them, they will not be inlined. If you define them, they will be inline.

So a header should look like

//header file

class myclass
{
public:
    void fn1()
    {} //defined into the class, so inlined by default

    void fn2();
};

inline void myclass::fn2()
{} //defined outside the class, so explicit inline is needed

And if myclass::fn2() definition goes into a proper source, must lose the inline keyword.