C++ .cpp 文件中的内联成员函数
我知道根据定义,内联成员函数应该进入标题。但是,如果无法将函数的实现放入标头中怎么办?让我们考虑这种情况:
File Ah
#pragma once
#include "B.h"
class A{
B b;
};
File Bh
#pragma once
class A; //forward declaration
class B{
inline A getA();
};
由于循环包含,我必须将 getA
的实现放入
B.cpp
#include "B.h"
#include "A.h"
inline A B::getA(){
return A();
}
编译器会内联 getA
吗?如果是,那么哪个内联关键字是重要的(标头中的关键字或 .cpp 文件中的关键字)?是否有另一种方法将内联成员函数的定义放入其 .cpp 文件中?
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
#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
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
引用自 C++ 常见问题解答:
每当编译器发现内联函数的任何使用时,编译器都需要查看该内联函数的定义。如果内联函数放置在头文件中,则通常是可能的。
不可以,除非在 B.cpp 本身中使用
getA()
。最佳实践:仅在定义之外类体。
不,至少我不知道。
Quoting from C++ FAQ:
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.
No, except when the the use of
getA()
is in B.cpp itself.Best practice: only in the definition outside the class body.
No, at least I don't know.
它不能在 B.cpp 的范围之外。编译器在每个编译单元的基础上运行,即它单独编译每个 .cpp 文件,因此如果它编译 C.cpp,它将没有可用的 getA() 代码,并且需要执行函数调用和让链接器修复它(或者,如果它确实按字面意思并尝试内联,最终会出现链接器错误。
inline
与static
具有相似的品质代码>)。唯一的例外是 LTCG,即链接时代码生成,它可在较新的编译器上使用。
在这种情况下,一种方法是使用另一个包含内联代码的头文件(有时称为 *.inl 文件)。
编辑: 至于哪个内联相关 - 它是类定义中的内联,即头文件中的内联。请记住,许多编译器对于什么可以内联以及什么应该内联有自己的想法。例如,gcc 可以完全禁用内联(-O0),或者它可以内联任何它认为值得内联的内容(例如 -O3)。
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.
inline
has similar qualities asstatic
).The only exception is LTCG, i.e. link-time code generation, which is available on newer compilers.
One approach in this case is to have another header file (sometimes named *.inl files) that contain the inlined code.
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).
我会从相反的方向来解决这个问题。
不要向函数添加内联声明(除非您也需要)。
唯一需要将内联声明添加到函数/方法的情况是,如果您在头文件中但在类声明之外定义了该函数。
Xh
X.cpp
给你更具体的案例。
删除所有内联规范。他们没有做你认为他们在做的事情。
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
X.cpp
To you more specific case.
Remove all the inline specifications. They are not doing what you think they are doing.
如今,大多数编译器都可以在链接时以及编译时执行内联。如果您的函数可能受益于内联,那么链接时间优化器很可能会这样做。
当链接器到达它时,除了编译器会将某些对象标记为可收集之外,关于编译器输出的内联状态的信息并不多,例如,因为内联函数或类模板实例出现在多个编译单元中,或者当多个符号共享一个名称时,例如 main 函数被定义两次,它应该会引发错误。这些都不会影响它将生成的实际代码。
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.
这是我的做法。
File Ah
File Bh
File Ch
只需包含“Ch”文件即可使用 getA() 方法。原始代码的唯一变化是 getA() 方法必须定义为公共方法而不是私有方法。
然而,正如你们许多人所解释的那样,这并不是真正有用。
Here is the way I did it.
File A.h
File B.h
File C.h
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.
However, as many of you explained it, this is not really useful.