我有一个类,其中包含许多小函数。所谓的小函数是指不进行任何处理而只返回文字值的函数。就像这样:
string Foo::method() const{
return "A";
}
我创建了一个头文件"Foo.h"和源文件"Foo.cpp"。但是由于函数非常小,我考虑将其放在头文件中。我有以下问题:
- 如果我将这些函数定义放在头文件中,是否会有性能或其他问题?我将有很多这样的函数。
- 我的理解是,在编译完成后,编译器将扩展头文件并将其放置在包含它的位置。这是正确的吗?
我有一个类,其中包含许多小函数。所谓的小函数是指不进行任何处理而只返回文字值的函数。就像这样:
string Foo::method() const{
return "A";
}
我创建了一个头文件"Foo.h"和源文件"Foo.cpp"。但是由于函数非常小,我考虑将其放在头文件中。我有以下问题:
inline string method() {
return something;
}
如果成员函数是在类内部定义的,则它们会隐式地成为内联函数。同样的事情也适用于它们:如果可以将它们放入头文件而没有麻烦,确实可以这样做。
因为函数的代码被放置在头文件中并且可见,编译器能够将对它们的调用内联,即直接将函数的代码放在调用点(不仅仅是因为你在前面加了inline关键字,而更多的是因为编译器决定这样做)。这可能会导致性能提升,因为编译器现在可以看到参数与函数局部变量匹配的位置,以及参数彼此之间没有别名 - 最后但并非最不重要的是,不再需要函数框架分配。
我的理解是,在编译完成时,编译器将扩展头文件并将其放置在其中包含的位置。正确吗?
是的,这是正确的。该函数将在包括其头文件的每个地方进行定义。编译器将通过消除其他实例来确保只将一个实例放入结果程序中。
根据您所使用的编译器及其设置,它可能会执行以下任何操作:
在许多情况下,编译器比您更有能力确定函数是否应该内联,因此没有必要猜测它。我喜欢在类中有许多小函数时使用隐式内联,只是因为将实现放在类中很方便。但对于较大的函数效果不佳。
另一件需要记住的事情是,如果您正在导出一个DLL /共享库中的类(我认为这不是一个好主意,但人们仍然这样做),您需要非常小心内联函数。如果建立DLL的编译器决定内联一个函数,您就会面临以下几个潜在问题:
由于头文件中的实现被隐式地内联,因此性能将会提高。就像你提到的一样,如果你的函数很小,内联操作对你非常有益。
你所说的编译器也是正确的。除了内联之外,在头文件或.cpp文件中的代码对编译器来说没有区别。
如果你的函数非常简单,可以将它们变为内联函数,这样你就必须把它们放入头文件中。除此之外,任何习惯都只是习惯而已。
是的,编译器在遇到 #include 语句时会展开头文件。
这取决于您所应用的编码标准,但:
小型函数没有循环和其他内容时,应进行内联处理以获得更好的性能(但代码略大,对于某些受限或嵌入式应用程序非常重要)。
如果在头文件中有函数体,则默认情况下会进行内联处理(这对于速度来说是一件好事)。
在编译器创建对象文件之前,会调用预处理器(gcc 的 -E 选项),并将结果发送给编译器,后者将代码转换为对象。
因此,简短的答案是:
-- 在头文件中声明函数对于速度来说很好(但空间不够用)--