简体   繁体   English

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

[英]C++ inline member function in .cpp file

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 Ah 档案啊

#pragma once
#include "B.h"

class A{
    B b;
};

File Bh 文件Bh

#pragma once

class A; //forward declaration

class B{
    inline A getA();
};

Due to the circular include I have to put the implementation of getA into 由于循环包含我必须把getA的实现

B.cpp B.cpp

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

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

Will the compiler inline getA ? 编译器内联getA吗? If so, which inline keyword is the significant one (the one in the header or the one in the .cpp file)? 如果是这样,哪个内联关键字是重要的(标题中的那个或.cpp文件中的那个)? Is there another way to put the definition of an inline member function into its .cpp file? 是否有另一种方法将内联成员函数的定义放入其.cpp文件中?

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. 注意:必须将函数的定义({...}之间的部分)放在头文件中,除非该函数仅在单个.cpp文件中使用。 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文件中调用它,则会从链接器中获得“未解析的外部”错误。

The compiler need to see the definition of 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. 不,至少我不知道。

It can't, outside the scope of B.cpp. 它不能超出B.cpp的范围。 The compiler operates on a per-compile-unit base, ie 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. inline has similar qualities as static ). 编译器在每个编译单元的基础上运行,即它单独编译每个.cpp文件,因此如果它编译C.cpp,它将没有getA()的代码可用,并且需要执行函数调用和让链接器修复它(或者,如果它真的把你带走了并尝试内联,它将最终出现链接器错误inline具有与static类似的特性)。

The only exception is LTCG, ie 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, ie 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)。

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. 您需要将内联声明添加到函数/方法的唯一时间是在头文件中但在类声明之外定义函数。

Xh 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. 他们没有做你认为他们正在做的事情。

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. 这些都不会影响它将生成的实际代码。

Here is the way I did it. 这是我做的方式。

File Ah 档案啊

#pragma once
#include "B.h"

class A {
    B b;
};

File Bh 文件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 Ch 文件Ch

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

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

Just include the "Ch" file to be able to use getA() method. 只需包含“Ch”文件即可使用getA()方法。 The only change with the original code is that the getA() method must be defined as public instead of private. 原始代码的唯一变化是getA()方法必须定义为public而不是private。

However, as many of you explained it, this is not really useful. 但是,正如你们许多人所解释的那样,这并不是很有用。

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). 该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见12.1,12.4和12.8)。 An inline function shall be defined in every translation unit in which it is odr-used. 内联函数应在每个使用它的翻译单元中定义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM