Why are class member functions inlined?

13,835

Solution 1

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.

Solution 2

The inline keyword has for a function 2 meanings:

  1. Code replacement: Wherever inline function is invoked, don't generate a function call for it but simply place the contents of the function at the place of its call (this is something similar to macro replacement, but type safe)
  2. One definition rule: Don't generate multiple definition for a inline function, only generate a single definition common for all (exception: static functions)

The 1st terminology ("Code replacement"), is simply a request to the compiler. which can be ignored as compiler is better to judge whether to put the text or a function call. (for example, virtual functions or recursive functions cannot be inlined).

The 2nd terminology ("One definition rule") is guaranteed to happen by any conforming compiler. This will generate only 1 definition for all translation units. This facility eases coder's work sometimes, as for smaller function one may not want to put its definition in .cpp file (e.g. getters, setters).
Moreover, for template function which are header only constructs, this effect is mandatory. Thus template functions are inline by default.

Examples:

class A {
public:
  void setMember (int i) { m_i = i; }
};

In this example mostly compiler would suffice both terminologies

class A {
  inline virtual ~A () = 0;
};
A::~A() {}

Here compiler can only suffice the 2nd requirement.

Solution 3

The only reason to make the method function inline is if you define it in the header.

If you define a method function in a header, and you do not put inline keyword, and you include the header in several header or source files, you would get multiple definition of the method.

c++11 standard in 9.3/2 Member functions [class.mfct] tells :

A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2) ...

Solution 4

When the definition is inside the class, it is treated as if it were declared inline, because it is assumed that class definitions live in header files that are used from more than one translation unit, so any non-inline definitions here would violate the One Definition Rule.

The compiler is, as always, free to inline whatever it thinks as long as it takes care that functions that are either explicitly or implicitly inline will not lead to linker errors. How it does that is left open by the language spec -- inlining the function of course works, but it is also acceptable to demote the symbol visibility or rename the symbol to a translation unit specific name (as if the function were in an anonymous namespace), or (as most of them do) communicate to the linker that multiple copies of that function may exist and that it should discard all but one of them.

So, in short, it is not treated any different from functions that are explicitly declared inline.

Solution 5

The compiler can ignore inlining if specified by the inline keyword. If the method implementation is present inside the class definition, that's a different thing, and can't be ignored. (well it can, but that makes the compiler non-conforming)

The reason behind the desing - I'm assuming a mechanism was needed where you can actually force the compiler to actually inline your functions, since the inline keyword doesn't mandate it. But in general, inline method definition is done only in cases like getter and setter methods, or some trivial 2-liners. And templates, but that's a different issue.

Inlining has to do with headers and source files in that the definition of the function must be visible to the compiler so it knows how to actually inline the call. It's more difficult to inline a function defined in an implementation file than one defined in a header.

EDIT: On a side note, the paragraph the op is reffering to is 7.1.2.3:

A function defined within a class definition is a inline function [...].

EDIT2:

Apparently, there are some difference between an inline function and inline substitution. The first is a property of a function, that doesn't only include inline substitution, the second means that the function body is actually pasted where it is called.

So the function can be inlined but not have its body pasted instead of being called.

Share:
13,835
vidit
Author by

vidit

So much to learn..

Updated on June 15, 2022

Comments

  • vidit
    vidit about 2 years

    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)

    • vidit
      vidit over 12 years
      @VJovic- msdn.microsoft.com/en-us/library/bw1hbe6y.aspx and many other places
    • BЈовић
      BЈовић over 12 years
      That is not c++ standard. What other places?
    • Luchian Grigore
      Luchian Grigore over 12 years
      @VJovic it says so in the standard. See my answer.
    • BЈовић
      BЈовић over 12 years
      That is a bug in MSDN's documentation. It should say The C++ standard says all member functions defined inside class definition must be inline
    • BЈовић
      BЈовић over 12 years
      @LuchianGrigore Yes, I saw it. Which paragraph in standard says so?
    • Luchian Grigore
      Luchian Grigore over 12 years
      @VJovic I stated that too - 7.1.2.3 from C++03.
    • vidit
      vidit over 12 years
      @VJovic- My bad.. I thought MSDN to be a reliable resource and at par with the standard, that's why referred to it and provided that link.
    • vidit
      vidit over 12 years
      @LuchianGrigore- Thanks for providing the reference in the C++ Standard.
    • jcoder
      jcoder over 12 years
      Defining functions in the class definitions causes them to have an implicit "inline" in their definition. That does not necessarily cause them to actually be inlined in the generated code though.
    • vidit
      vidit over 12 years
      @JohnB- So that means compiler will ignore inline keyword in such a case, right?
  • vidit
    vidit over 12 years
    But in general, inline method definition is done only in cases like getter and setter methods, or some trivial 2-liners does that mean a big function inside class definition wont be inline?
  • Luchian Grigore
    Luchian Grigore over 12 years
    @vidit it would, but defeat the purpose. Move a big implementation in an implementation file.
  • Luchian Grigore
    Luchian Grigore over 12 years
    @vidit yes, define functions outside if you don't want them inlined.
  • Johannes Schaub - litb
    Johannes Schaub - litb over 12 years
    i -1ed this. see the other answers for the reason
  • jcoder
    jcoder over 12 years
    I can't believe that the standard says that two functions declared in the class definition are required to be actually inlined. Wouldn't that for example mean that two functions declared this way could never call each other as they would have to each contain the whole body of the other function which is clearly impossible.
  • Luchian Grigore
    Luchian Grigore over 12 years
    @JohannesSchaub-litb can you be more precise?
  • Luchian Grigore
    Luchian Grigore over 12 years
    @JohnB that's a very good point. Maybe it can be an inline function (I mean, that's what the standard says) and its body not be pasted in the actual code?...
  • vidit
    vidit over 12 years
    @JohnB - Good point.. I should include this in my question, if you dont mind?
  • Johannes Schaub - litb
    Johannes Schaub - litb over 12 years
    emilios answer has all the details. and contradicts your answer, which is incorrect.
  • Luchian Grigore
    Luchian Grigore over 12 years
    @JohannesSchaub-litb can you tell me exactly where my answer is wrong? I can't see from emilio's answer. Also, please not the difference between inline function and inline substitution.
  • vidit
    vidit over 12 years
    +1 for the gr8 explanation. You already answered update 2. So the correct definition of inline is "It tells the compiler that the function definition can be repeated."
  • Ruslan
    Ruslan almost 8 years
    The reason for my downvote is that you say "a mechanism was needed where you can actually force the compiler to actually inline your functions". This is wrong: the functions defined in class definition can't be forced to be inlined if using the standard syntax only — due to the as if rule. What this was needed for is to avoid multiple definition of these functions when you include your header defining the class in multiple translation units. It would be counterproductive to require all such functions to be explicitly marked inline, so they are inline implicitly.
  • Ruslan
    Ruslan almost 8 years
    One can consider the inline word in the syntax to mean "this function's definition will be inlined into multiple translation units without breaking ODR". I.e. inlining on the source code level, not on the machine code.
  • rps
    rps about 4 years
    @Ruslan ,correct clarification. When you declare a func. included in a header file as inline, in whichever TU source you INCLUDE the header file, the compiler will substitute the source of the func. WHEREVER it has referenced in the TU source before compiling & not set up a func. definition on a call stack. If inline declaration is not used & if due to inclusion of the header file in multiple TU sources, multiple func. definitions end up getting set up & the linker will flag error of violation of ODR. So, if your want to inline the function, you'd declare the function inline in the 1st place.