为什么 C++ 内联函数在头文件中?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5057021/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:16:52  来源:igfitidea点击:

Why are C++ inline functions in the header?

c++inlinetheorylanguage-designc++-faq

提问by thecoshman

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

NB这不是关于如何使用内联函数或它们如何工作的问题,而是关于它们为什么以它们的方式完成的问题。

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:

类成员函数的声明不需要将函数定义为inline,它只是函数的实际实现。例如,在头文件中:

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

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

那么,为什么一类的内联函数的实现必须要在头文件?为什么我不能把内联函数放在.cpp文件中?如果我尝试将内联定义放在.cpp文件中,我会得到如下错误:

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

回答by CB Bailey

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

inline函数的定义不必在头文件中,但由于内联函数的定义规则相同,因此在使用它的每个翻译单元中都必须存在相同的函数定义。

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 inlinedoes not mean that the compiler cannot inline the function.

如果要将函数的定义放在单个源文件中,则不应声明它inline。未声明的函数并不inline意味着编译器不能内联该函数。

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

你是否应该声明一个函数inline通常是你应该根据哪个版本的定义规则最适合你遵循的选择;添加inline然后受到后续约束的限制几乎没有意义。

回答by jalf

There are two ways to look at it:

有两种方法可以查看它:

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

  2. functions defined in the header must be marked inlinebecause 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 inlinekeyword suppresses this, allowing multiple translation units to contain (identical) definitions.

  1. 内联函数在头文件中定义,因为为了内联函数调用,编译器必须能够看到函数体。对于一个简单的编译器来说,函数体必须与调用位于同一个翻译单元中。(现代编译器可以跨翻译单元进行优化,因此即使函数定义在单独的翻译单元中,函数调用也可能被内联,但这些优化很昂贵,并不总是启用,并且并不总是受支持编译器)

  2. 在头文件中定义的函数必须被标记inline,否则,包含头文件的每个翻译单元都将包含函数的定义,并且链接器会抱怨多个定义(违反一个定义规则)。的inline关键字抑制此,允许多个翻译单元包含(相同)的定义。

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

这两种解释实际上归结为inline关键字并不完全符合您的预期这一事实。

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.

C++ 编译器可以随时应用内联优化(用被调用函数的主体替换函数调用,节省调用开销),只要它不改变程序的可观察行为。

The inlinekeyword makes it easierfor 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 hasto inline the function, and notusing the keyword doesn't forbid the compiler from inlining the function.

inline关键字使得它更容易让编译器应用此优化,通过允许函数定义在多个翻译单元是可见的,但使用关键字并不意味着编译器内联函数,而不是使用关键字不禁止编译器内联函数。

回答by 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...)

这是 C++ 编译器的限制。如果将函数放在头文件中,则所有可以内联它的 cpp 文件都可以看到函数的“源”,并且内联可以由编译器完成。否则内联必须由链接器完成(每个 cpp 文件都单独编译在一个 obj 文件中)。问题是在链接器中这样做会困难得多。“模板”类/函数也存在类似的问题。它们需要由编译器实例化,因为链接器在实例化(创建其专用版本)时会遇到问题。一些较新的编译器/链接器可以执行“两遍”编译/链接,其中编译器执行第一遍,然后链接器执行其工作并调用编译器来解决未解决的问题(内联/模板...)

回答by sbi

The reason is that the compiler has to actually see the definitionin 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.)

请记住,C 和 C++ 使用非常简单的编译模型,其中编译器每次只能看到一个翻译单元。(这无法导出,这是只有一个供应商实际实施它的主要原因。)

回答by Erik

The c++ inlinekeyword 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 inlineto be a real function that is called instead of getting code inlined at the point where it's called.

c++inline关键字具有误导性,它并不意味着“内联此函数”。如果一个函数被定义为内联函数,它只是意味着只要所有定义都相等,它就可以被定义多次。将函数标记inline为被调用的真实函数而不是在调用它的点处内联代码是完全合法的。

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

模板需要在头文件中定义一个函数,因为例如模板化的类并不是真正的类,它是一个类的模板,您可以对其进行多种变体。为了使编译器能够在您使用 Foo 模板创建 Foo 类时创建一个Foo<int>::bar()函数, 的实际定义必须是可见的。Foo<T>::bar()

回答by flamewave000

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

我知道这是一个旧线程,但我想我应该提到extern关键字。我最近遇到了这个问题并解决如下

Helper.h

Helper.h

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

Helper.cpp

Helper.cpp

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

回答by Leandro T. C. Melo

Because the compiler needs to see them in order to inlinethem. 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.

回答by Saurabh Raoot

Inline Functions

内联函数

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

在 C++ 中,宏只是内联函数。所以现在宏在编译器的控制之下。

  • Important: If we define a function inside class it will become Inlineautomatically
  • 重要提示:如果我们在类中定义一个函数,它将自动变为内联

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

Inline 函数的代码在它被调用的地方被替换,因此它减少了调用函数的开销。

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

这里 getSpeed 和 setSpeed 函数都将变为内联