.cpp 文件中的 C++ 内联成员函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3992980/
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 14:13:50  来源:igfitidea点击:

C++ inline member function in .cpp file

c++functioninlinemember

提问by Mat

I know that inline member functions by definition should go into the header. But what if it's not possible to put the implementation of the function into the header? Let's take this situation:

我知道根据定义内联成员函数应该进入标题。但是如果无法将函数的实现放入头文件中怎么办?让我们来看看这种情况:

File A.h

档案啊

#pragma once
#include "B.h"

class A{
    B b;
};

File B.h

文件 Bh

#pragma once

class A; //forward declaration

class B{
    inline A getA();
};

Due to the circular include I have to put the implementation of getAinto

由于通函包含,我必须将实施getA放入

B.cpp

B.cpp

#include "B.h"
#include "A.h"

inline A B::getA(){
    return A();
}

Will the compiler inline getA? If so, which inline keyword is the significant one (the one in the header or the one in the .cpp file)? Is there another way to put the definition of an inline member function into its .cpp file?

编译器会内联getA吗?如果是这样,哪个内联关键字是重要的(标题中的一个或 .cpp 文件中的一个)?还有另一种方法可以将内联成员函数的定义放入其 .cpp 文件中吗?

回答by Arun

Quoting from C++ FAQ:

引用C++ FAQ

Note: It's imperative that the function's definition (the part between the {...}) be placed in a header file, unless the function is used only in a single .cpp file. In particular, if you put the inline function's definition into a .cpp file and you call it from some other .cpp file, you'll get an "unresolved external" error from the linker.

注意:函数的定义({...} 之间的部分)必须放在头文件中,除非该函数仅在单个 .cpp 文件中使用。特别是,如果您将内联函数的定义放入 .cpp 文件并从某个其他 .cpp 文件调用它,您将收到来自链接器的“未解析的外部”错误。

The compiler need to see the definitionof the inline function whenever it finds any use of that inline function. That is typically possible if the inline function is placed in a header file.

编译器在发现任何使用该内联函数时需要查看该内联函数的定义。如果将内联函数放在头文件中,这通常是可能的。

Will the compiler inline getA?

编译器会内联 getA 吗?

No, except when the the use of getA()is in B.cpp itself.

不,除非getA()在 B.cpp 本身中使用。

If so, which inline keyword is the significant one (the one in the header or the one in the cpp)?

如果是这样,哪个内联关键字是重要的(标题中的一个或 cpp 中的一个)?

Best practice: only in the definition outside the class body.

最佳实践:只在类体之外定义。

Is there another way to put the definition of an inline member function into it's cpp file?

还有另一种方法可以将内联成员函数的定义放入它的 cpp 文件中吗?

No, at least I don't know.

不,至少我不知道。

回答by EboMike

It can't, outside the scope of B.cpp. The compiler operates on a per-compile-unit base, i.e. it compiles each .cpp file individually, so if it compiles C.cpp, it won't have the code for getA() available and will need to perform a function call and have the linker fix it up (or, if it really took you by the word and tried to inline, it will have end up with a linker error. inlinehas similar qualities as static).

它不能,在 B.cpp 的范围之外。编译器在每个编译单元的基础上运行,即它单独编译每个 .cpp 文件,因此如果它编译 C.cpp,它将没有可用的 getA() 代码并且需要执行函数调用和让链接器修复它(或者,如果它真的让你知道并试图内联,它最终会出现链接器错误。inline具有与 相似的特性static)。

The only exception is LTCG, i.e. link-time code generation, which is available on newer compilers.

唯一的例外是 LTCG,即链接时代码生成,它可用于较新的编译器。

One approach in this case is to have another header file (sometimes named *.inl files) that contain the inlined code.

在这种情况下,一种方法是使用包含内联代码的另一个头文件(有时称为 *.inl 文件)。

EDIT: As for which inline is relevant - it's the one in the class definition, i.e. in the header file. Keep in mind that many compilers have their own mind on what can and should be inlined. gcc for example can disable inlining completely (-O0), or it can inline anything that it deems worth inlining (like -O3).

编辑:至于哪个内联是相关的 - 它是类定义中的一个,即在头文件中。请记住,许多编译器对可以和应该内联的内容有自己的看法。例如,gcc 可以完全禁用内联 (-O0),或者它可以内联它认为值得内联的任何内容(如 -O3)。

回答by Martin York

I would go about this from the opposite direction.

我会从相反的方向进行。

Don't add inline declarations to your function (unless you need too).

不要向您的函数添加内联声明(除非您也需要)。

The only time you need to add the inline declaration to a function/method is if you define the function in a header file but outside the class declaration.

唯一需要向函数/方法添加内联声明的时间是在头文件中但在类声明之外定义函数。

X.h

Xh

class X
{
    public:
        int getX()   { return 4;} // No inline because it is part of the class.
                                  // The compiler knows that needs an inline tag
        int getY();
        int getZ();
};

inline
int X::getY()  { return 5;}       // This needs to be explicitly declared inline.
                                  // Otherwise the linker will complain about
                                  // multiple definitions in compilation units.

X.cpp

X.cpp

 // Never declare anything inline in the cpp file.

 int X::getZ() { return 6; }

To you more specific case.
Remove all the inline specifications. They are not doing what you think they are doing.

给你更具体的情况。
删除所有内联规范。他们没有做你认为他们在做的事情。

回答by SingleNegationElimination

These days, most compilers can perform inlining at link time, as well as compile time. If your function is likely to benefit from inlining, then the Link Time optimizer is likely to do just that.

现在,大多数编译器可以在链接时和编译时执行内联。如果您的函数可能受益于内联,那么链接时间优化器很可能会这样做。

By the time the linker gets to it, not much about the inline status of compiler output is available, except that the compiler will flag certain objects as being collectible, for instance because an inline function or class template instance appears in multiple compilation units, or it should raise an error when multiple symbols share a name, such as the main function being defined twice. None of this has influence on the actual code it will generate.

当链接器到达它时,关于编译器输出的内联状态的信息并不多,除了编译器会将某些对象标记为可收集的,例如因为内联函数或类模板实例出现在多个编译单元中,或者当多个符号共享一个名称时,它应该会引发错误,例如主函数被定义两次。这些都不会影响它将生成的实际代码。

回答by Pascal Viguié

Here is the way I did it.

这是我这样做的方式。

File A.h

档案啊

#pragma once
#include "B.h"

class A {
    B b;
};

File B.h

文件 Bh

#pragma once

class B {
public:
    template<class T> inline T getA() {
        assert(NULL); // Use 'getA<A>()' template specialization only!
        return NULL;
    }
};

class A; // Forward declaration
template<> inline A B::getA<A>();

File C.h

档案频道

#pragma once
#include "A.h"
#include "B.h"

// Implement template specialization here!
template<> inline A B::getA<A>() { return A(); }

Just include the "C.h" file to be able to use getA() method. The only change with the original code is that the getA() method must be defined as public instead of private.

只需包含“Ch”文件即可使用 getA() 方法。与原始代码的唯一变化是 getA() 方法必须定义为 public 而不是 private。

However, as many of you explained it, this is not really useful.

但是,正如你们中的许多人所解释的那样,这并不是很有用。

回答by isnullxbh

ISO/IEC 14882:2014

ISO/IEC 14882:2014

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.

每个程序都应包含该程序中 odr 使用的每个非内联函数或变量的一个定义;无需诊断。定义可以显式地出现在程序中,可以在标准或用户定义的库中找到,或者(在适当的时候)它是隐式定义的(见 12.1、12.4 和 12.8)。内联函数应在每个使用 odr 的翻译单元中定义。