Why are class member functions inlined?
Asked Answered
M

6

36

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)

Marchak answered 16/3, 2012 at 8:45 Comment(10)
@VJovic- msdn.microsoft.com/en-us/library/bw1hbe6y.aspx and many other placesMarchak
That is not c++ standard. What other places?Deletion
@VJovic it says so in the standard. See my answer.Exurbanite
That is a bug in MSDN's documentation. It should say The C++ standard says all member functions defined inside class definition must be inlineDeletion
@LuchianGrigore Yes, I saw it. Which paragraph in standard says so?Deletion
@VJovic I stated that too - 7.1.2.3 from C++03.Exurbanite
@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.Marchak
@LuchianGrigore- Thanks for providing the reference in the C++ Standard.Marchak
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.Sedimentology
@JohnB- So that means compiler will ignore inline keyword in such a case, right?Marchak
S
65

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.

Skyeskyhigh answered 16/3, 2012 at 9:3 Comment(3)
+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."Marchak
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.Creamery
@Creamery ,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.Coranto
A
22

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.

Aigrette answered 16/3, 2012 at 9:20 Comment(2)
"(exception: static functions)" I guess you mean just the free static functions, and not static member functions, right?Stevenage
@Seangle, true. This is meant for free static functions. Here static supersedes inline and hence every translation unit (viz. .cpp file) will still have its own copy of that function.Aigrette
C
9

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) ...

Christos answered 16/3, 2012 at 8:52 Comment(1)
"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." Aren't member functions that are defined in classes in header files inline by default? Or do you mean definition outside the class body but still in the header file?Stevenage
E
3

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.

Engvall answered 16/3, 2012 at 8:57 Comment(0)
E
1

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.

Exurbanite answered 16/3, 2012 at 8:47 Comment(11)
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?Marchak
@Marchak it would, but defeat the purpose. Move a big implementation in an implementation file.Exurbanite
@Marchak yes, define functions outside if you don't want them inlined.Exurbanite
i -1ed this. see the other answers for the reasonCurhan
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.Sedimentology
@JohannesSchaub-litb can you be more precise?Exurbanite
@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?...Exurbanite
@JohnB - Good point.. I should include this in my question, if you dont mind?Marchak
emilios answer has all the details. and contradicts your answer, which is incorrect.Curhan
@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.Exurbanite
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.Creamery
P
0

the two things you reffer to are different aspects and not to be confused with.

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

2) I have also heard that compiler can ignore inlining of a function

1) is when you define the member functions inside the class declaration itself. ie: in the header files. for that you do not have to provide any keyword( ie: inline)

2) You can specify a function as inline by explicitly using the inline keyword. this is actually a request to the compiler. the compiler may or may not make the function inline according to some rules of optimization.

Propulsion answered 16/3, 2012 at 9:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.