ChatGPT解决这个技术问题 Extra ChatGPT

Why are C++ inline functions in the header?

NB This is not a question about how to use inline functions or how they work, more why they are done the way they are.

The declaration of a class member function does not need to define a function as inline, it is only the actual implementation of the function. For example, in the header file:

struct foo{
    void bar(); // no need to define this as inline
}

So why does the inline implementation of a classes function have to be in the header file? Why can't I put the inline function the .cpp file? If I were to try to put the inline definition in the .cpp file I would get an error along the lines of:

error LNK2019: unresolved external symbol 
"public: void __thiscall foo::bar(void)"
(?bar@foo@@QAEXXZ) referenced in function _main 
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe 
: fatal error LNK1120: 1 unresolved externals
@Charles I would say that second link my be similar, but I am asking more about logic behind why inline works the way it does.
In that case, I think you may have misunderstood either "inline" or "header files"; neither of your assertions are true. You can have an inline implementation of a member function and you can put inline function definitions in a header file, it's just it might not be a good idea. Can you clarify your question?
Post edit, I think you may be asking about situations when inline appears on a definition but not a prior declaration vs vice versa. If so, this may help: stackoverflow.com/questions/4924912/…

E
Enlico

The definition of an inline function doesn't have to be in a header file but, because of the one definition rule (ODR) for inline functions, an identical definition for the function must exist in every translation unit that uses it.

The easiest way to achieve this is by putting the definition in a header file.

If you want to put the definition of a function in a single source file then you shouldn't declare it inline. A function not declared inline does not mean that the compiler cannot inline the function.

Whether you should declare a function inline or not is usually a choice that you should make based on which version of the one definition rules it makes most sense for you to follow; adding inline and then being restricted by the subsequent constraints makes little sense.


But doesn't the compiler compile the .cpp file, which includes the .h files... so that when it does compile a .cpp file it has both the deceleration as well as the source files. Other header files pulled in are just their so the compiler can 'trust' that those functions do exist and will be implemented in some other source file
This is actually a much better answer than mine, +1 from me!
@thecoshman: There are two distinctions. Source file vs header file. By convention, a header file usually refers to a source file that isn't that basis for a translation unit but is only #included from other source files. Then there is declaration vs definition. You can have declarations or definitions of functions in either header files or 'normal' source files. I'm afraid I'm not sure what you are asking in your comment.
don't worry, I get why it is now... though I am not sure who really answered this one. A combination of yours and @Xanatos's answer explained it for me.
K
KeyC0de

There are two ways to look at it:

Inline functions are defined in the header because, in order to inline a function call, the compiler must be able to see the function body. For a naive compiler to do that, the function body must be in the same translation unit as the call. (A modern compiler can optimize across translation units, and so a function call may be inlined even though the function definition is in a separate translation unit, but these optimizations are expensive, aren't always enabled, and weren't always supported by the compiler) functions defined in the header must be marked inline because otherwise, every translation unit which includes the header will contain a definition of the function, and the linker will complain about multiple definitions (a violation of the One Definition Rule). The inline keyword suppresses this, allowing multiple translation units to contain (identical) definitions.

The two explanations really boil down to the fact that the inline keyword doesn't exactly do what you'd expect.

A C++ compiler is free to apply the inlining optimization (replace a function call with the body of the called function, saving the call overhead) any time it likes, as long as it doesn't alter the observable behavior of the program.

The inline keyword makes it easier for the compiler to apply this optimization, by allowing the function definition to be visible in multiple translation units, but using the keyword doesn't mean the compiler has to inline the function, and not using the keyword doesn't forbid the compiler from inlining the function.


x
xanatos

This is a limit of the C++ compiler. If you put the function in the header, all the cpp files where it can be inlined can see the "source" of your function and the inlining can be done by the compiler. Otherwhise the inlining would have to be done by the linker (each cpp file is compiled in an obj file separately). The problem is that it would be much more difficult to do it in the linker. A similar problem exists with "template" classes/functions. They need to be instantiated by the compiler, because the linker would have problem instantiating (creating a specialized version of) them. Some newer compiler/linker can do a "two pass" compilation/linking where the compiler does a first pass, then the linker does its work and call the compiler to resolve unresolved things (inline/templates...)


Oh I see! yes, its not for the class it self the uses the inline function, its other code that makes use of the inline functions. They only see the header file for the class that is being inlined!
I disagree with this answer, it's not a C++ compiler limit; it's purely how the language rules are specified. The language rules allow a simple compilation model but they don't prohibit alternative implementations.
I agree with @Charles. In fact there are compilers that inline functions across translation units, so this definitely isn't due to compiler limitations.
Whilst this answer does seem to have some technical errors, it did help me see how the compiler works with header files and such.
E
Erik

The c++ inline keyword is misleading, it doesn't mean "inline this function". If a function is defined as inline, it simply means that it can be defined multiple times as long as all definitions are equal. It's perfectly legal for a function marked inline to be a real function that is called instead of getting code inlined at the point where it's called.

Defining a function in a header file is needed for templates, since e.g. a templated class isn't really a class, it's a template for a class which you can make multiple variations of. In order for the compiler to be able to e.g. make a Foo<int>::bar() function when you use the Foo template to create a Foo class, the actual definition of Foo<T>::bar() must be visible.


And since it is a template for a class, it isn't called a template class, but a class template.
The first paragraph is completely right (and I wish I could emphasize "misleading"), but I don't see the need for the non sequitur into templates.
Some compilers will use it as a hint that the function can probably be inlined, but indeed, it is not guaranteed to be inlined just because you declare it inline (nor does not-declaring it inline guarantee that it won't be inlined).
This is the best description, but I agree with @ThomasEdleson that the segue isn't helpful and in fact is what keeps me from upvoting.
s
sbi

The reason is that the compiler has to actually see the definition in order to be able to drop it in in place of the call.

Remember that C and C++ use a very simplistic compilation model, where the compiler always only sees one translation unit at a time. (This fails for export, which is the main reason only one vendor actually implemented it.)


f
flamewave000

I know this is an old thread but thought I should mention that the extern keyword. I've recently ran into this issue and solved as follows

Helper.h

namespace DX
{
    extern inline void ThrowIfFailed(HRESULT hr);
}

Helper.cpp

namespace DX
{
    inline void ThrowIfFailed(HRESULT hr)
    {
        if (FAILED(hr))
        {
            std::stringstream ss;
            ss << "#" << hr;
            throw std::exception(ss.str().c_str());
        }
    }
}

This is generally not going to result in the function actually being inlined unless you are using Whole Program Optimization (WPO).
L
Leandro T. C. Melo

Because the compiler needs to see them in order to inline them. And headers files are the "components" which are commonly included in other translation units.

#include "file.h"
// Ok, now me (the compiler) can see the definition of that inline function. 
// So I'm able to replace calls for the actual implementation.

L
Louis Cloete

Inline Functions

In C++ a macro is nothing but inline function. SO now macros are under control of compiler.

Important : If we define a function inside class it will become Inline automatically

Code of Inline function is replaced at the place it is called, so it reduce the overhead of calling function.

In some cases Inlining of function can not work, Such as

If static variable used inside inline function.

If function is complicated.

If recursive call of function

If address of function taken implicitely or explicitely

Function defined outside class as below may become inline

inline int AddTwoVar(int x,int y); //This may not become inline 

inline int AddTwoVar(int x,int y) { return x + y; } // This becomes inline

Function defined inside class also become inline

// Inline SpeedMeter functions
class SpeedMeter
{
    int speed;
    public:
    int getSpeed() const { return speed; }
    void setSpeed(int varSpeed) { speed = varSpeed; }
};
int main()
{
    SpeedMeter objSM;
    objSM.setSpeed(80);
    int speedValue = A.getSpeed();
} 

Here both getSpeed and setSpeed functions will become inline


eh, some nice info perhaps, but doesn't really attempt to explain why. Maybe you do, but just aren't making it clear.
The following statement is not true: "Important : If we define a function inside class it will become Inline automatically" Not even if you write "inline" in the declaration/definition you can be sure that it's being in fact inlined. Not even for templates. Maybe you meant that the compiler automatically assumes the "inline" keyword, yet doesn't have to follow and what I've noticed is that in most cases it doesn't inline such in-header definitions, not even for simple constexpr functions with basic arithmetics.
Hey thanks for comments ...Below are lines from Thinking in C++ micc.unifi.it/bertini/download/programmazione/… Page 400 .. Please check .. Please upvote if you agree. Thanks ..... Inlines inside classes To define an inline function, you must ordinarily precede the function definition with the inline keyword. However, this is not necessary inside a class definition. Any function you define inside a class definition is automatically an inline.
The authors of that book can claim what they want, because they write books and not code. This is something I had to analyze deeply in order to make my portable 3d demos fit in less than 64kb by avoiding inlined code as much as possible. Programming is about facts and not religion, so it doesn't really matter if some "god programmer" said it in a book if it doesn't represent what happens in practice. And most C++ books out there are a collection of bad advice, in which from time to time you get to find some neat trick to add to your repertory.
Hey @PabloAriel Thanks... Please analyse and let me know .. I am ok to update this answer as per analysis