Why are class member functions inlined?

2019-01-21 19:41发布

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)

6条回答
我欲成王,谁敢阻挡
2楼-- · 2019-01-21 20:12

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.

查看更多
放我归山
3楼-- · 2019-01-21 20:20

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.

查看更多
虎瘦雄心在
4楼-- · 2019-01-21 20:29

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.

查看更多
一夜七次
5楼-- · 2019-01-21 20:29

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.

查看更多
太酷不给撩
6楼-- · 2019-01-21 20:31

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

查看更多
家丑人穷心不美
7楼-- · 2019-01-21 20:33

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.

查看更多
登录 后发表回答